Patch translucent sliver app bar

This commit is contained in:
Ming Ming 2024-05-20 22:14:27 +08:00
parent 7d1d59b880
commit ac298e14ab

View file

@ -1,6 +1,7 @@
// ignore_for_file: deprecated_member_use, unnecessary_null_comparison, curly_braces_in_flow_control_structures, deprecated_member_use_from_same_package // ignore_for_file: deprecated_member_use, unnecessary_null_comparison, curly_braces_in_flow_control_structures, deprecated_member_use_from_same_package
import 'dart:math' as math; import 'dart:math' as math;
import 'dart:ui';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -27,11 +28,11 @@ class TranslucentSliverAppBar extends StatefulWidget {
this.flexibleSpace, this.flexibleSpace,
this.bottom, this.bottom,
this.elevation, this.elevation,
this.scrolledUnderElevation,
this.shadowColor, this.shadowColor,
this.surfaceTintColor, this.surfaceTintColor,
this.forceElevated = false, this.forceElevated = false,
this.backgroundColor, this.backgroundColor,
this.scrolledUnderBackgroundColor,
this.foregroundColor, this.foregroundColor,
this.iconTheme, this.iconTheme,
this.actionsIconTheme, this.actionsIconTheme,
@ -55,7 +56,8 @@ class TranslucentSliverAppBar extends StatefulWidget {
this.systemOverlayStyle, this.systemOverlayStyle,
this.forceMaterialTransparency = false, this.forceMaterialTransparency = false,
this.clipBehavior, this.clipBehavior,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'), this.blurFilter,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'),
assert(stretchTriggerOffset > 0.0), assert(stretchTriggerOffset > 0.0),
assert( assert(
collapsedHeight == null || collapsedHeight >= toolbarHeight, collapsedHeight == null || collapsedHeight >= toolbarHeight,
@ -95,11 +97,11 @@ class TranslucentSliverAppBar extends StatefulWidget {
this.flexibleSpace, this.flexibleSpace,
this.bottom, this.bottom,
this.elevation, this.elevation,
this.scrolledUnderElevation,
this.shadowColor, this.shadowColor,
this.surfaceTintColor, this.surfaceTintColor,
this.forceElevated = false, this.forceElevated = false,
this.backgroundColor, this.backgroundColor,
this.scrolledUnderBackgroundColor,
this.foregroundColor, this.foregroundColor,
this.iconTheme, this.iconTheme,
this.actionsIconTheme, this.actionsIconTheme,
@ -123,7 +125,8 @@ class TranslucentSliverAppBar extends StatefulWidget {
this.systemOverlayStyle, this.systemOverlayStyle,
this.forceMaterialTransparency = false, this.forceMaterialTransparency = false,
this.clipBehavior, this.clipBehavior,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'), this.blurFilter,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'),
assert(stretchTriggerOffset > 0.0), assert(stretchTriggerOffset > 0.0),
assert( assert(
collapsedHeight == null || collapsedHeight >= toolbarHeight, collapsedHeight == null || collapsedHeight >= toolbarHeight,
@ -163,11 +166,11 @@ class TranslucentSliverAppBar extends StatefulWidget {
this.flexibleSpace, this.flexibleSpace,
this.bottom, this.bottom,
this.elevation, this.elevation,
this.scrolledUnderElevation,
this.shadowColor, this.shadowColor,
this.surfaceTintColor, this.surfaceTintColor,
this.forceElevated = false, this.forceElevated = false,
this.backgroundColor, this.backgroundColor,
this.scrolledUnderBackgroundColor,
this.foregroundColor, this.foregroundColor,
this.iconTheme, this.iconTheme,
this.actionsIconTheme, this.actionsIconTheme,
@ -191,7 +194,8 @@ class TranslucentSliverAppBar extends StatefulWidget {
this.systemOverlayStyle, this.systemOverlayStyle,
this.forceMaterialTransparency = false, this.forceMaterialTransparency = false,
this.clipBehavior, this.clipBehavior,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'), this.blurFilter,
}) : assert(floating || !snap, 'The "snap" argument only makes sense for floating app bars.'),
assert(stretchTriggerOffset > 0.0), assert(stretchTriggerOffset > 0.0),
assert( assert(
collapsedHeight == null || collapsedHeight >= toolbarHeight, collapsedHeight == null || collapsedHeight >= toolbarHeight,
@ -234,11 +238,6 @@ class TranslucentSliverAppBar extends StatefulWidget {
/// This property is used to configure an [AppBar]. /// This property is used to configure an [AppBar].
final double? elevation; final double? elevation;
/// {@macro flutter.material.appbar.scrolledUnderElevation}
///
/// This property is used to configure an [AppBar].
final double? scrolledUnderElevation;
/// {@macro flutter.material.appbar.shadowColor} /// {@macro flutter.material.appbar.shadowColor}
/// ///
/// This property is used to configure an [AppBar]. /// This property is used to configure an [AppBar].
@ -265,6 +264,8 @@ class TranslucentSliverAppBar extends StatefulWidget {
/// This property is used to configure an [AppBar]. /// This property is used to configure an [AppBar].
final Color? backgroundColor; final Color? backgroundColor;
final Color? scrolledUnderBackgroundColor;
/// {@macro flutter.material.appbar.foregroundColor} /// {@macro flutter.material.appbar.foregroundColor}
/// ///
/// This property is used to configure an [AppBar]. /// This property is used to configure an [AppBar].
@ -456,6 +457,8 @@ class TranslucentSliverAppBar extends StatefulWidget {
final _SliverAppVariant _variant; final _SliverAppVariant _variant;
final ImageFilter? blurFilter;
@override @override
State<TranslucentSliverAppBar> createState() => _SliverAppBarState(); State<TranslucentSliverAppBar> createState() => _SliverAppBarState();
} }
@ -569,11 +572,11 @@ class _SliverAppBarState extends State<TranslucentSliverAppBar>
flexibleSpace: effectiveFlexibleSpace, flexibleSpace: effectiveFlexibleSpace,
bottom: widget.bottom, bottom: widget.bottom,
elevation: widget.elevation, elevation: widget.elevation,
scrolledUnderElevation: widget.scrolledUnderElevation,
shadowColor: widget.shadowColor, shadowColor: widget.shadowColor,
surfaceTintColor: widget.surfaceTintColor, surfaceTintColor: widget.surfaceTintColor,
forceElevated: widget.forceElevated, forceElevated: widget.forceElevated,
backgroundColor: widget.backgroundColor, backgroundColor: widget.backgroundColor,
scrolledUnderBackgroundColor: widget.scrolledUnderBackgroundColor,
foregroundColor: widget.foregroundColor, foregroundColor: widget.foregroundColor,
iconTheme: widget.iconTheme, iconTheme: widget.iconTheme,
actionsIconTheme: widget.actionsIconTheme, actionsIconTheme: widget.actionsIconTheme,
@ -598,6 +601,7 @@ class _SliverAppBarState extends State<TranslucentSliverAppBar>
forceMaterialTransparency: widget.forceMaterialTransparency, forceMaterialTransparency: widget.forceMaterialTransparency,
clipBehavior: widget.clipBehavior, clipBehavior: widget.clipBehavior,
variant: widget._variant, variant: widget._variant,
blurFilter: widget.blurFilter,
), ),
), ),
); );
@ -650,7 +654,6 @@ class _ScrollUnderFlexibleSpace extends StatelessWidget {
// title to keep the visual hierarchy the same even with larger font // title to keep the visual hierarchy the same even with larger font
// sizes. To opt out, wrap the [title] widget in a [MediaQuery] widget // sizes. To opt out, wrap the [title] widget in a [MediaQuery] widget
// with a different TextScaler. // with a different TextScaler.
// TODO(tahatesser): Add link to Material spec when available, https://github.com/flutter/flutter/issues/58769.
return MediaQuery.withClampedTextScaling( return MediaQuery.withClampedTextScaling(
maxScaleFactor: _kMaxTitleTextScaleFactor, maxScaleFactor: _kMaxTitleTextScaleFactor,
// This column will assume the full height of the parent Stack. // This column will assume the full height of the parent Stack.
@ -684,11 +687,11 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
required this.flexibleSpace, required this.flexibleSpace,
required this.bottom, required this.bottom,
required this.elevation, required this.elevation,
required this.scrolledUnderElevation,
required this.shadowColor, required this.shadowColor,
required this.surfaceTintColor, required this.surfaceTintColor,
required this.forceElevated, required this.forceElevated,
required this.backgroundColor, required this.backgroundColor,
required this.scrolledUnderBackgroundColor,
required this.foregroundColor, required this.foregroundColor,
required this.iconTheme, required this.iconTheme,
required this.actionsIconTheme, required this.actionsIconTheme,
@ -714,7 +717,8 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
required this.forceMaterialTransparency, required this.forceMaterialTransparency,
required this.clipBehavior, required this.clipBehavior,
required this.variant, required this.variant,
}) : assert(primary || topPadding == 0.0), required this.blurFilter,
}) : assert(primary || topPadding == 0.0),
_bottomHeight = bottom?.preferredSize.height ?? 0.0; _bottomHeight = bottom?.preferredSize.height ?? 0.0;
final Widget? leading; final Widget? leading;
@ -724,11 +728,11 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final Widget? flexibleSpace; final Widget? flexibleSpace;
final PreferredSizeWidget? bottom; final PreferredSizeWidget? bottom;
final double? elevation; final double? elevation;
final double? scrolledUnderElevation;
final Color? shadowColor; final Color? shadowColor;
final Color? surfaceTintColor; final Color? surfaceTintColor;
final bool forceElevated; final bool forceElevated;
final Color? backgroundColor; final Color? backgroundColor;
final Color? scrolledUnderBackgroundColor;
final Color? foregroundColor; final Color? foregroundColor;
final IconThemeData? iconTheme; final IconThemeData? iconTheme;
final IconThemeData? actionsIconTheme; final IconThemeData? actionsIconTheme;
@ -751,6 +755,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final bool forceMaterialTransparency; final bool forceMaterialTransparency;
final Clip? clipBehavior; final Clip? clipBehavior;
final _SliverAppVariant variant; final _SliverAppVariant variant;
final ImageFilter? blurFilter;
@override @override
double get minExtent => collapsedHeight; double get minExtent => collapsedHeight;
@ -798,40 +803,56 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
toolbarOpacity: toolbarOpacity, toolbarOpacity: toolbarOpacity,
isScrolledUnder: isScrolledUnder, isScrolledUnder: isScrolledUnder,
hasLeading: leading != null || automaticallyImplyLeading, hasLeading: leading != null || automaticallyImplyLeading,
child: AppBar( child: Stack(
clipBehavior: clipBehavior, children: [
leading: leading, SizedBox(
automaticallyImplyLeading: automaticallyImplyLeading, width: double.infinity,
title: effectiveTitle, height: math.max(minExtent, maxExtent - shrinkOffset),
actions: actions, child: ClipRect(
flexibleSpace: (title == null && flexibleSpace != null && !excludeHeaderSemantics) child: BackdropFilter(
? Semantics( filter: blurFilter ?? ImageFilter.blur(),
header: true, child: const ColoredBox(
child: flexibleSpace, color: Colors.transparent,
) ),
: flexibleSpace, ),
bottom: bottom, ),
elevation: isScrolledUnder ? elevation : 0.0, ),
scrolledUnderElevation: scrolledUnderElevation, AppBar(
shadowColor: shadowColor, clipBehavior: clipBehavior,
surfaceTintColor: surfaceTintColor, leading: leading,
backgroundColor: backgroundColor, automaticallyImplyLeading: automaticallyImplyLeading,
foregroundColor: foregroundColor, title: effectiveTitle,
iconTheme: iconTheme, actions: actions,
actionsIconTheme: actionsIconTheme, flexibleSpace: (title == null && flexibleSpace != null && !excludeHeaderSemantics)
primary: primary, ? Semantics(
centerTitle: centerTitle, header: true,
excludeHeaderSemantics: excludeHeaderSemantics, child: flexibleSpace,
titleSpacing: titleSpacing, )
shape: shape, : flexibleSpace,
toolbarOpacity: toolbarOpacity, bottom: bottom,
bottomOpacity: pinned ? 1.0 : clampDouble(visibleMainHeight / _bottomHeight, 0.0, 1.0), elevation: isScrolledUnder ? elevation : 0.0,
toolbarHeight: toolbarHeight, scrolledUnderElevation: 0,
leadingWidth: leadingWidth, shadowColor: shadowColor,
toolbarTextStyle: toolbarTextStyle, surfaceTintColor: surfaceTintColor,
titleTextStyle: titleTextStyle, backgroundColor: isScrolledUnder ? scrolledUnderBackgroundColor : backgroundColor,
systemOverlayStyle: systemOverlayStyle, foregroundColor: foregroundColor,
forceMaterialTransparency: forceMaterialTransparency, iconTheme: iconTheme,
actionsIconTheme: actionsIconTheme,
primary: primary,
centerTitle: centerTitle,
excludeHeaderSemantics: excludeHeaderSemantics,
titleSpacing: titleSpacing,
shape: shape,
toolbarOpacity: toolbarOpacity,
bottomOpacity: pinned ? 1.0 : clampDouble(visibleMainHeight / _bottomHeight, 0.0, 1.0),
toolbarHeight: toolbarHeight,
leadingWidth: leadingWidth,
toolbarTextStyle: toolbarTextStyle,
titleTextStyle: titleTextStyle,
systemOverlayStyle: systemOverlayStyle,
forceMaterialTransparency: forceMaterialTransparency,
),
],
), ),
); );
return appBar; return appBar;
@ -849,6 +870,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|| elevation != oldDelegate.elevation || elevation != oldDelegate.elevation
|| shadowColor != oldDelegate.shadowColor || shadowColor != oldDelegate.shadowColor
|| backgroundColor != oldDelegate.backgroundColor || backgroundColor != oldDelegate.backgroundColor
|| scrolledUnderBackgroundColor != oldDelegate.scrolledUnderBackgroundColor
|| foregroundColor != oldDelegate.foregroundColor || foregroundColor != oldDelegate.foregroundColor
|| iconTheme != oldDelegate.iconTheme || iconTheme != oldDelegate.iconTheme
|| actionsIconTheme != oldDelegate.actionsIconTheme || actionsIconTheme != oldDelegate.actionsIconTheme