diff --git a/lib/src/app_bar/app_bar.dart b/lib/src/app_bar/app_bar.dart index 9a65a40..e5ce205 100644 --- a/lib/src/app_bar/app_bar.dart +++ b/lib/src/app_bar/app_bar.dart @@ -240,9 +240,9 @@ class _AnimatedAppBar extends AnimatedWidget { @override Widget build(BuildContext context) { - final state = MorphingState(parent: parent, child: child, t: t); + final state = MorphingState(parent: parent, child: this.child, t: t); - return AppBar( + Widget child = AppBar( leading: AnimatedLeading(state), // We manually determine the leadings to be able to animate between them. automaticallyImplyLeading: false, @@ -276,6 +276,18 @@ class _AnimatedAppBar extends AnimatedWidget { forceMaterialTransparency: state.forceMaterialTransparency, clipBehavior: state.clipBehavior, ); + if (state.flexibleSpaceBarSettings case final settings?) { + child = FlexibleSpaceBar.createSettings( + toolbarOpacity: settings.toolbarOpacity, + minExtent: settings.minExtent, + maxExtent: settings.maxExtent, + isScrolledUnder: settings.isScrolledUnder, + hasLeading: settings.hasLeading, + currentExtent: settings.currentExtent, + child: child, + ); + } + return child; } } diff --git a/lib/src/app_bar/sliver_app_bar.dart b/lib/src/app_bar/sliver_app_bar.dart index 0d470dd..0535c1c 100644 --- a/lib/src/app_bar/sliver_app_bar.dart +++ b/lib/src/app_bar/sliver_app_bar.dart @@ -101,6 +101,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { required this.systemOverlayStyle, required this.forceMaterialTransparency, required this.clipBehavior, + required this.accessibleNavigation, }) : assert(primary || topPadding == 0.0), assert( !floating || @@ -147,6 +148,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { final bool forceMaterialTransparency; final Clip? clipBehavior; final double _bottomHeight; + final bool accessibleNavigation; @override double get minExtent => collapsedHeight; @@ -188,18 +190,27 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { final visibleToolbarHeight = visibleMainHeight - _bottomHeight - extraToolbarHeight; + final isScrolledUnder = overlapsContent || + forceElevated || + (pinned && shrinkOffset > maxExtent - minExtent); final isPinnedWithOpacityFade = pinned && floating && bottom != null && extraToolbarHeight == 0.0; - final toolbarOpacity = !pinned || isPinnedWithOpacityFade - ? (visibleToolbarHeight / (toolbarHeight ?? kToolbarHeight)) - .clamp(0.0, 1.0) - : 1.0; + final toolbarOpacity = + !accessibleNavigation && (!pinned || isPinnedWithOpacityFade) + ? clampDouble( + visibleToolbarHeight / (toolbarHeight ?? kToolbarHeight), + 0, + 1, + ) + : 1.0; final appBar = FlexibleSpaceBar.createSettings( minExtent: minExtent, maxExtent: maxExtent, currentExtent: math.max(minExtent, maxExtent - shrinkOffset), toolbarOpacity: toolbarOpacity, + isScrolledUnder: isScrolledUnder, + hasLeading: leading != null || automaticallyImplyLeading, child: MorphingAppBar( heroTag: heroTag, leading: leading, @@ -211,11 +222,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { ? Semantics(header: true, child: flexibleSpace) : flexibleSpace, bottom: bottom, - elevation: forceElevated || - overlapsContent || - (pinned && shrinkOffset > maxExtent - minExtent) - ? elevation ?? 4 - : 0, + elevation: isScrolledUnder ? elevation : 0.0, scrolledUnderElevation: scrolledUnderElevation, shadowColor: shadowColor, surfaceTintColor: surfaceTintColor, @@ -280,7 +287,8 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate { titleTextStyle != oldDelegate.titleTextStyle || systemOverlayStyle != oldDelegate.systemOverlayStyle || forceMaterialTransparency != oldDelegate.forceMaterialTransparency || - clipBehavior != oldDelegate.clipBehavior; + clipBehavior != oldDelegate.clipBehavior || + accessibleNavigation != oldDelegate.accessibleNavigation; } @override @@ -570,6 +578,7 @@ class _SliverAppBarState extends State systemOverlayStyle: widget.systemOverlayStyle, forceMaterialTransparency: widget.forceMaterialTransparency, clipBehavior: widget.clipBehavior, + accessibleNavigation: MediaQuery.accessibleNavigationOf(context), ), ), ); diff --git a/lib/src/app_bar/state.dart b/lib/src/app_bar/state.dart index 4d54a2f..c7cab2c 100644 --- a/lib/src/app_bar/state.dart +++ b/lib/src/app_bar/state.dart @@ -88,6 +88,41 @@ class MorphingState { )?.toRgb() ?? Colors.transparent; } + + FlexibleSpaceBarSettings? get flexibleSpaceBarSettings { + final parentSettings = parent.flexibleSpaceBarSettings; + final childSettings = child.flexibleSpaceBarSettings; + if (parentSettings == null && childSettings == null) return null; + + return FlexibleSpaceBarSettings( + toolbarOpacity: lerpDouble( + parentSettings?.toolbarOpacity, + childSettings?.toolbarOpacity, + t, + )!, + minExtent: lerpDouble( + parentSettings?.minExtent, + childSettings?.minExtent, + t, + )!, + maxExtent: lerpDouble( + parentSettings?.maxExtent, + childSettings?.maxExtent, + t, + )!, + currentExtent: lerpDouble( + parentSettings?.currentExtent, + childSettings?.currentExtent, + t, + )!, + isScrolledUnder: t < 0.5 + ? parentSettings?.isScrolledUnder + : childSettings?.isScrolledUnder, + hasLeading: + t < 0.5 ? parentSettings?.hasLeading : childSettings?.hasLeading, + child: const SizedBox(), + ); + } } extension type _OklabColor( @@ -190,10 +225,13 @@ extension type _OklabColor( class EndState { EndState(BuildContext context, this.appBar) : theme = context.theme, - leading = AnimatedLeading.resolveLeading(context, appBar); + leading = AnimatedLeading.resolveLeading(context, appBar), + flexibleSpaceBarSettings = context + .dependOnInheritedWidgetOfExactType(); final ThemeData theme; AppBarTheme get appBarTheme => theme.appBarTheme; + final FlexibleSpaceBarSettings? flexibleSpaceBarSettings; final AppBar appBar;