Skip to content

Commit

Permalink
Fix FlexibleSpaceBar during animation
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasWanke committed Jan 25, 2025
1 parent 9d5a213 commit 50808c7
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 13 deletions.
16 changes: 14 additions & 2 deletions lib/src/app_bar/app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}
}

Expand Down
29 changes: 19 additions & 10 deletions lib/src/app_bar/sliver_app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -570,6 +578,7 @@ class _SliverAppBarState extends State<MorphingSliverAppBar>
systemOverlayStyle: widget.systemOverlayStyle,
forceMaterialTransparency: widget.forceMaterialTransparency,
clipBehavior: widget.clipBehavior,
accessibleNavigation: MediaQuery.accessibleNavigationOf(context),
),
),
);
Expand Down
40 changes: 39 additions & 1 deletion lib/src/app_bar/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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<FlexibleSpaceBarSettings>();

final ThemeData theme;
AppBarTheme get appBarTheme => theme.appBarTheme;
final FlexibleSpaceBarSettings? flexibleSpaceBarSettings;

final AppBar appBar;

Expand Down

0 comments on commit 50808c7

Please sign in to comment.