improved nav bar visibility

This commit is contained in:
Thibault Deckers 2022-05-13 13:38:25 +09:00
parent b0df94a4fa
commit fecfa45a29
4 changed files with 98 additions and 58 deletions

View file

@ -350,37 +350,45 @@ class _CollectionScrollViewState extends State<_CollectionScrollView> {
Widget _buildDraggableScrollView(ScrollView scrollView, CollectionLens collection) { Widget _buildDraggableScrollView(ScrollView scrollView, CollectionLens collection) {
return ValueListenableBuilder<double>( return ValueListenableBuilder<double>(
valueListenable: widget.appBarHeightNotifier, valueListenable: widget.appBarHeightNotifier,
builder: (context, appBarHeight, child) => Selector<MediaQueryData, double>( builder: (context, appBarHeight, child) {
selector: (context, mq) => mq.effectiveBottomPadding, return Selector<MediaQueryData, double>(
builder: (context, mqPaddingBottom, child) { selector: (context, mq) => mq.effectiveBottomPadding,
return Selector<SectionedListLayout<AvesEntry>, List<SectionLayout>>( builder: (context, mqPaddingBottom, child) {
selector: (context, layout) => layout.sectionLayouts, return Selector<Settings, bool>(
builder: (context, sectionLayouts, child) { selector: (context, s) => s.showBottomNavigationBar,
return DraggableScrollbar( builder: (context, showBottomNavigationBar, child) {
backgroundColor: Colors.white, final navBarHeight = showBottomNavigationBar ? AppBottomNavBar.height : 0;
scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight), return Selector<SectionedListLayout<AvesEntry>, List<SectionLayout>>(
scrollThumbBuilder: avesScrollThumbBuilder( selector: (context, layout) => layout.sectionLayouts,
height: avesScrollThumbHeight, builder: (context, sectionLayouts, child) {
backgroundColor: Colors.white, return DraggableScrollbar(
), backgroundColor: Colors.white,
controller: widget.scrollController, scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
crumbsBuilder: () => _getCrumbs(sectionLayouts), scrollThumbBuilder: avesScrollThumbBuilder(
padding: EdgeInsets.only( height: avesScrollThumbHeight,
// padding to keep scroll thumb between app bar above and nav bar below backgroundColor: Colors.white,
top: appBarHeight, ),
bottom: mqPaddingBottom, controller: widget.scrollController,
), crumbsBuilder: () => _getCrumbs(sectionLayouts),
labelTextBuilder: (offsetY) => CollectionDraggableThumbLabel( padding: EdgeInsets.only(
collection: collection, // padding to keep scroll thumb between app bar above and nav bar below
offsetY: offsetY, top: appBarHeight,
), bottom: navBarHeight + mqPaddingBottom,
crumbTextBuilder: (label) => DraggableCrumbLabel(label: label), ),
child: scrollView, labelTextBuilder: (offsetY) => CollectionDraggableThumbLabel(
); collection: collection,
}, offsetY: offsetY,
); ),
}, crumbTextBuilder: (label) => DraggableCrumbLabel(label: label),
), child: scrollView,
);
},
);
},
);
},
);
},
); );
} }

View file

@ -512,28 +512,41 @@ class _FilterScrollView<T extends CollectionFilter> extends StatelessWidget {
} }
Widget _buildDraggableScrollView(ScrollView scrollView) { Widget _buildDraggableScrollView(ScrollView scrollView) {
return Selector<MediaQueryData, double>( return ValueListenableBuilder<double>(
selector: (context, mq) => mq.effectiveBottomPadding, valueListenable: appBarHeightNotifier,
builder: (context, mqPaddingBottom, child) => DraggableScrollbar( builder: (context, appBarHeight, child) {
backgroundColor: Colors.white, return Selector<MediaQueryData, double>(
scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight), selector: (context, mq) => mq.effectiveBottomPadding,
scrollThumbBuilder: avesScrollThumbBuilder( builder: (context, mqPaddingBottom, child) {
height: avesScrollThumbHeight, return Selector<Settings, bool>(
backgroundColor: Colors.white, selector: (context, s) => s.showBottomNavigationBar,
), builder: (context, showBottomNavigationBar, child) {
controller: scrollController, final navBarHeight = showBottomNavigationBar ? AppBottomNavBar.height : 0;
padding: EdgeInsets.only( return DraggableScrollbar(
// padding to keep scroll thumb between app bar above and nav bar below backgroundColor: Colors.white,
top: appBarHeightNotifier.value, scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
bottom: mqPaddingBottom, scrollThumbBuilder: avesScrollThumbBuilder(
), height: avesScrollThumbHeight,
labelTextBuilder: (offsetY) => FilterDraggableThumbLabel<T>( backgroundColor: Colors.white,
sortFactor: sortFactor, ),
offsetY: offsetY, controller: scrollController,
), padding: EdgeInsets.only(
crumbTextBuilder: (offsetY) => const SizedBox(), // padding to keep scroll thumb between app bar above and nav bar below
child: scrollView, top: appBarHeight,
), bottom: navBarHeight + mqPaddingBottom,
),
labelTextBuilder: (offsetY) => FilterDraggableThumbLabel<T>(
sortFactor: sortFactor,
offsetY: offsetY,
),
crumbTextBuilder: (offsetY) => const SizedBox(),
child: scrollView,
);
},
);
},
);
},
); );
} }

View file

@ -1,17 +1,21 @@
import 'dart:async'; import 'dart:async';
import 'dart:math';
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class FloatingNavBar extends StatefulWidget { class FloatingNavBar extends StatefulWidget {
final ScrollController? scrollController; final ScrollController? scrollController;
final Stream<DraggableScrollBarEvent> events; final Stream<DraggableScrollBarEvent> events;
final double childHeight;
final Widget child; final Widget child;
const FloatingNavBar({ const FloatingNavBar({
super.key, super.key,
required this.scrollController, required this.scrollController,
required this.events, required this.events,
required this.childHeight,
required this.child, required this.child,
}); });
@ -90,8 +94,6 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
} }
void _onScrollChange() { void _onScrollChange() {
if (_isDragging) return;
final scrollController = widget.scrollController; final scrollController = widget.scrollController;
if (scrollController == null) return; if (scrollController == null) return;
@ -99,13 +101,22 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
_delta += offset - (_lastOffset ?? offset); _delta += offset - (_lastOffset ?? offset);
_lastOffset = offset; _lastOffset = offset;
if (_isDragging) return;
final after = scrollController.position.extentAfter;
final childHeight = widget.childHeight;
if (after < childHeight && scrollController.position.userScrollDirection == ScrollDirection.reverse) {
_controller.value = min(_controller.value, after / childHeight);
_delta = 0;
return;
}
if (_delta.abs() > _deltaThreshold) { if (_delta.abs() > _deltaThreshold) {
if (_delta > 0) { if (_delta > 0) {
_hide(); _hide();
} else { } else {
_show(); _show();
} }
_delta = 0;
} }
} }
@ -122,7 +133,13 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
} }
} }
void _show() => _controller.reverse(); void _show() {
_controller.reverse();
_delta = 0;
}
void _hide() => _controller.forward(); void _hide() {
_controller.forward();
_delta = 0;
}
} }

View file

@ -6,6 +6,7 @@ import 'package:aves/model/source/collection_source.dart';
import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart'; import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
import 'package:aves/widgets/common/extensions/build_context.dart'; import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/extensions/media_query.dart';
import 'package:aves/widgets/common/fx/blurred.dart'; import 'package:aves/widgets/common/fx/blurred.dart';
import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart';
import 'package:aves/widgets/navigation/nav_bar/floating.dart'; import 'package:aves/widgets/navigation/nav_bar/floating.dart';
@ -79,6 +80,7 @@ class AppBottomNavBar extends StatelessWidget {
child: FloatingNavBar( child: FloatingNavBar(
scrollController: PrimaryScrollController.of(context), scrollController: PrimaryScrollController.of(context),
events: events, events: events,
childHeight: height + context.select<MediaQueryData, double>((mq) => mq.effectiveBottomPadding),
child: SafeArea( child: SafeArea(
child: child, child: child,
), ),