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) {
return ValueListenableBuilder<double>(
valueListenable: widget.appBarHeightNotifier,
builder: (context, appBarHeight, child) => Selector<MediaQueryData, double>(
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) {
return Selector<SectionedListLayout<AvesEntry>, List<SectionLayout>>(
selector: (context, layout) => layout.sectionLayouts,
builder: (context, sectionLayouts, child) {
return DraggableScrollbar(
backgroundColor: Colors.white,
scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
scrollThumbBuilder: avesScrollThumbBuilder(
height: avesScrollThumbHeight,
backgroundColor: Colors.white,
),
controller: widget.scrollController,
crumbsBuilder: () => _getCrumbs(sectionLayouts),
padding: EdgeInsets.only(
// padding to keep scroll thumb between app bar above and nav bar below
top: appBarHeight,
bottom: mqPaddingBottom,
),
labelTextBuilder: (offsetY) => CollectionDraggableThumbLabel(
collection: collection,
offsetY: offsetY,
),
crumbTextBuilder: (label) => DraggableCrumbLabel(label: label),
child: scrollView,
);
},
);
},
),
builder: (context, appBarHeight, child) {
return Selector<MediaQueryData, double>(
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) {
return Selector<Settings, bool>(
selector: (context, s) => s.showBottomNavigationBar,
builder: (context, showBottomNavigationBar, child) {
final navBarHeight = showBottomNavigationBar ? AppBottomNavBar.height : 0;
return Selector<SectionedListLayout<AvesEntry>, List<SectionLayout>>(
selector: (context, layout) => layout.sectionLayouts,
builder: (context, sectionLayouts, child) {
return DraggableScrollbar(
backgroundColor: Colors.white,
scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
scrollThumbBuilder: avesScrollThumbBuilder(
height: avesScrollThumbHeight,
backgroundColor: Colors.white,
),
controller: widget.scrollController,
crumbsBuilder: () => _getCrumbs(sectionLayouts),
padding: EdgeInsets.only(
// padding to keep scroll thumb between app bar above and nav bar below
top: appBarHeight,
bottom: navBarHeight + mqPaddingBottom,
),
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) {
return Selector<MediaQueryData, double>(
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) => DraggableScrollbar(
backgroundColor: Colors.white,
scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
scrollThumbBuilder: avesScrollThumbBuilder(
height: avesScrollThumbHeight,
backgroundColor: Colors.white,
),
controller: scrollController,
padding: EdgeInsets.only(
// padding to keep scroll thumb between app bar above and nav bar below
top: appBarHeightNotifier.value,
bottom: mqPaddingBottom,
),
labelTextBuilder: (offsetY) => FilterDraggableThumbLabel<T>(
sortFactor: sortFactor,
offsetY: offsetY,
),
crumbTextBuilder: (offsetY) => const SizedBox(),
child: scrollView,
),
return ValueListenableBuilder<double>(
valueListenable: appBarHeightNotifier,
builder: (context, appBarHeight, child) {
return Selector<MediaQueryData, double>(
selector: (context, mq) => mq.effectiveBottomPadding,
builder: (context, mqPaddingBottom, child) {
return Selector<Settings, bool>(
selector: (context, s) => s.showBottomNavigationBar,
builder: (context, showBottomNavigationBar, child) {
final navBarHeight = showBottomNavigationBar ? AppBottomNavBar.height : 0;
return DraggableScrollbar(
backgroundColor: Colors.white,
scrollThumbSize: Size(avesScrollThumbWidth, avesScrollThumbHeight),
scrollThumbBuilder: avesScrollThumbBuilder(
height: avesScrollThumbHeight,
backgroundColor: Colors.white,
),
controller: scrollController,
padding: EdgeInsets.only(
// padding to keep scroll thumb between app bar above and nav bar below
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:math';
import 'package:aves/widgets/common/basic/draggable_scrollbar.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class FloatingNavBar extends StatefulWidget {
final ScrollController? scrollController;
final Stream<DraggableScrollBarEvent> events;
final double childHeight;
final Widget child;
const FloatingNavBar({
super.key,
required this.scrollController,
required this.events,
required this.childHeight,
required this.child,
});
@ -90,8 +94,6 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
}
void _onScrollChange() {
if (_isDragging) return;
final scrollController = widget.scrollController;
if (scrollController == null) return;
@ -99,13 +101,22 @@ class _FloatingNavBarState extends State<FloatingNavBar> with SingleTickerProvid
_delta += 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 > 0) {
_hide();
} else {
_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/common/basic/draggable_scrollbar.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/filter_grids/albums_page.dart';
import 'package:aves/widgets/navigation/nav_bar/floating.dart';
@ -79,6 +80,7 @@ class AppBottomNavBar extends StatelessWidget {
child: FloatingNavBar(
scrollController: PrimaryScrollController.of(context),
events: events,
childHeight: height + context.select<MediaQueryData, double>((mq) => mq.effectiveBottomPadding),
child: SafeArea(
child: child,
),