mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 16:56:19 +01:00
708 lines
25 KiB
Dart
708 lines
25 KiB
Dart
// 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 'package:flutter/foundation.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/rendering.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:nc_photos/theme.dart';
|
|
|
|
/// A translucent sliver app bar used in home pages
|
|
///
|
|
/// This calss is adopted from Flutter's SliverAppBar
|
|
class TranslucentSliverAppBar extends StatefulWidget {
|
|
/// Creates a material design app bar that can be placed in a [CustomScrollView].
|
|
///
|
|
/// The arguments [forceElevated], [primary], [floating], [pinned], [snap]
|
|
/// and [automaticallyImplyLeading] must not be null.
|
|
const TranslucentSliverAppBar({
|
|
Key? key,
|
|
this.leading,
|
|
this.automaticallyImplyLeading = true,
|
|
this.title,
|
|
this.actions,
|
|
this.flexibleSpace,
|
|
this.bottom,
|
|
this.elevation,
|
|
this.shadowColor,
|
|
this.surfaceTintColor,
|
|
this.forceElevated = false,
|
|
this.backgroundColor,
|
|
this.scrolledUnderBackgroundColor,
|
|
this.foregroundColor,
|
|
@Deprecated(
|
|
'This property is no longer used, please use systemOverlayStyle instead. '
|
|
'This feature was deprecated after v2.4.0-0.0.pre.',
|
|
)
|
|
this.brightness,
|
|
this.iconTheme,
|
|
this.actionsIconTheme,
|
|
@Deprecated(
|
|
'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
|
|
'This feature was deprecated after v2.4.0-0.0.pre.',
|
|
)
|
|
this.textTheme,
|
|
this.primary = true,
|
|
this.centerTitle,
|
|
this.excludeHeaderSemantics = false,
|
|
this.titleSpacing,
|
|
this.collapsedHeight,
|
|
this.expandedHeight,
|
|
this.floating = false,
|
|
this.pinned = false,
|
|
this.snap = false,
|
|
this.stretch = false,
|
|
this.stretchTriggerOffset = 100.0,
|
|
this.onStretchTrigger,
|
|
this.shape,
|
|
this.toolbarHeight = kToolbarHeight,
|
|
this.leadingWidth,
|
|
@Deprecated(
|
|
'This property is obsolete and is false by default. '
|
|
'This feature was deprecated after v2.4.0-0.0.pre.',
|
|
)
|
|
this.backwardsCompatibility,
|
|
this.toolbarTextStyle,
|
|
this.titleTextStyle,
|
|
this.systemOverlayStyle,
|
|
}) : assert(automaticallyImplyLeading != null),
|
|
assert(forceElevated != null),
|
|
assert(primary != null),
|
|
assert(floating != null),
|
|
assert(pinned != null),
|
|
assert(snap != null),
|
|
assert(stretch != null),
|
|
assert(toolbarHeight != null),
|
|
assert(floating || !snap,
|
|
'The "snap" argument only makes sense for floating app bars.'),
|
|
assert(stretchTriggerOffset > 0.0),
|
|
assert(collapsedHeight == null || collapsedHeight >= toolbarHeight,
|
|
'The "collapsedHeight" argument has to be larger than or equal to [toolbarHeight].'),
|
|
super(key: key);
|
|
|
|
/// {@macro flutter.material.appbar.leading}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Widget? leading;
|
|
|
|
/// {@macro flutter.material.appbar.automaticallyImplyLeading}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final bool automaticallyImplyLeading;
|
|
|
|
/// {@macro flutter.material.appbar.title}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Widget? title;
|
|
|
|
/// {@macro flutter.material.appbar.actions}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final List<Widget>? actions;
|
|
|
|
/// {@macro flutter.material.appbar.flexibleSpace}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Widget? flexibleSpace;
|
|
|
|
/// {@macro flutter.material.appbar.bottom}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final PreferredSizeWidget? bottom;
|
|
|
|
/// {@macro flutter.material.appbar.elevation}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final double? elevation;
|
|
|
|
/// {@macro flutter.material.appbar.shadowColor}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Color? shadowColor;
|
|
|
|
/// {@macro flutter.material.appbar.surfaceTintColor}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Color? surfaceTintColor;
|
|
|
|
/// Whether to show the shadow appropriate for the [elevation] even if the
|
|
/// content is not scrolled under the [AppBar].
|
|
///
|
|
/// Defaults to false, meaning that the [elevation] is only applied when the
|
|
/// [AppBar] is being displayed over content that is scrolled under it.
|
|
///
|
|
/// When set to true, the [elevation] is applied regardless.
|
|
///
|
|
/// Ignored when [elevation] is zero.
|
|
final bool forceElevated;
|
|
|
|
/// {@macro flutter.material.appbar.backgroundColor}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Color? backgroundColor;
|
|
|
|
final Color? scrolledUnderBackgroundColor;
|
|
|
|
/// {@macro flutter.material.appbar.foregroundColor}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final Color? foregroundColor;
|
|
|
|
/// {@macro flutter.material.appbar.brightness}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
@Deprecated(
|
|
'This property is no longer used, please use systemOverlayStyle instead. '
|
|
'This feature was deprecated after v2.4.0-0.0.pre.',
|
|
)
|
|
final Brightness? brightness;
|
|
|
|
/// {@macro flutter.material.appbar.iconTheme}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final IconThemeData? iconTheme;
|
|
|
|
/// {@macro flutter.material.appbar.actionsIconTheme}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final IconThemeData? actionsIconTheme;
|
|
|
|
/// {@macro flutter.material.appbar.textTheme}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
@Deprecated(
|
|
'This property is no longer used, please use toolbarTextStyle and titleTextStyle instead. '
|
|
'This feature was deprecated after v2.4.0-0.0.pre.',
|
|
)
|
|
final TextTheme? textTheme;
|
|
|
|
/// {@macro flutter.material.appbar.primary}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final bool primary;
|
|
|
|
/// {@macro flutter.material.appbar.centerTitle}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final bool? centerTitle;
|
|
|
|
/// {@macro flutter.material.appbar.excludeHeaderSemantics}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final bool excludeHeaderSemantics;
|
|
|
|
/// {@macro flutter.material.appbar.titleSpacing}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final double? titleSpacing;
|
|
|
|
/// Defines the height of the app bar when it is collapsed.
|
|
///
|
|
/// By default, the collapsed height is [toolbarHeight]. If [bottom] widget is
|
|
/// specified, then its height from [PreferredSizeWidget.preferredSize] is
|
|
/// added to the height. If [primary] is true, then the [MediaQuery] top
|
|
/// padding, [EdgeInsets.top] of [MediaQueryData.padding], is added as well.
|
|
///
|
|
/// If [pinned] and [floating] are true, with [bottom] set, the default
|
|
/// collapsed height is only the height of [PreferredSizeWidget.preferredSize]
|
|
/// with the [MediaQuery] top padding.
|
|
final double? collapsedHeight;
|
|
|
|
/// The size of the app bar when it is fully expanded.
|
|
///
|
|
/// By default, the total height of the toolbar and the bottom widget (if
|
|
/// any). If a [flexibleSpace] widget is specified this height should be big
|
|
/// enough to accommodate whatever that widget contains.
|
|
///
|
|
/// This does not include the status bar height (which will be automatically
|
|
/// included if [primary] is true).
|
|
final double? expandedHeight;
|
|
|
|
/// Whether the app bar should become visible as soon as the user scrolls
|
|
/// towards the app bar.
|
|
///
|
|
/// Otherwise, the user will need to scroll near the top of the scroll view to
|
|
/// reveal the app bar.
|
|
///
|
|
/// If [snap] is true then a scroll that exposes the app bar will trigger an
|
|
/// animation that slides the entire app bar into view. Similarly if a scroll
|
|
/// dismisses the app bar, the animation will slide it completely out of view.
|
|
///
|
|
/// ## Animated Examples
|
|
///
|
|
/// The following animations show how the app bar changes its scrolling
|
|
/// behavior based on the value of this property.
|
|
///
|
|
/// * App bar with [floating] set to false:
|
|
/// {@animation 476 400 https://flutter.github.io/assets-for-api-docs/assets/material/app_bar.mp4}
|
|
/// * App bar with [floating] set to true:
|
|
/// {@animation 476 400 https://flutter.github.io/assets-for-api-docs/assets/material/app_bar_floating.mp4}
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [SliverAppBar] for more animated examples of how this property changes the
|
|
/// behavior of the app bar in combination with [pinned] and [snap].
|
|
final bool floating;
|
|
|
|
/// Whether the app bar should remain visible at the start of the scroll view.
|
|
///
|
|
/// The app bar can still expand and contract as the user scrolls, but it will
|
|
/// remain visible rather than being scrolled out of view.
|
|
///
|
|
/// ## Animated Examples
|
|
///
|
|
/// The following animations show how the app bar changes its scrolling
|
|
/// behavior based on the value of this property.
|
|
///
|
|
/// * App bar with [pinned] set to false:
|
|
/// {@animation 476 400 https://flutter.github.io/assets-for-api-docs/assets/material/app_bar.mp4}
|
|
/// * App bar with [pinned] set to true:
|
|
/// {@animation 476 400 https://flutter.github.io/assets-for-api-docs/assets/material/app_bar_pinned.mp4}
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [SliverAppBar] for more animated examples of how this property changes the
|
|
/// behavior of the app bar in combination with [floating].
|
|
final bool pinned;
|
|
|
|
/// {@macro flutter.material.appbar.shape}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final ShapeBorder? shape;
|
|
|
|
/// If [snap] and [floating] are true then the floating app bar will "snap"
|
|
/// into view.
|
|
///
|
|
/// If [snap] is true then a scroll that exposes the floating app bar will
|
|
/// trigger an animation that slides the entire app bar into view. Similarly
|
|
/// if a scroll dismisses the app bar, the animation will slide the app bar
|
|
/// completely out of view. Additionally, setting [snap] to true will fully
|
|
/// expand the floating app bar when the framework tries to reveal the
|
|
/// contents of the app bar by calling [RenderObject.showOnScreen]. For
|
|
/// example, when a [TextField] in the floating app bar gains focus, if [snap]
|
|
/// is true, the framework will always fully expand the floating app bar, in
|
|
/// order to reveal the focused [TextField].
|
|
///
|
|
/// Snapping only applies when the app bar is floating, not when the app bar
|
|
/// appears at the top of its scroll view.
|
|
///
|
|
/// ## Animated Examples
|
|
///
|
|
/// The following animations show how the app bar changes its scrolling
|
|
/// behavior based on the value of this property.
|
|
///
|
|
/// * App bar with [snap] set to false:
|
|
/// {@animation 476 400 https://flutter.github.io/assets-for-api-docs/assets/material/app_bar_floating.mp4}
|
|
/// * App bar with [snap] set to true:
|
|
/// {@animation 476 400 https://flutter.github.io/assets-for-api-docs/assets/material/app_bar_floating_snap.mp4}
|
|
///
|
|
/// See also:
|
|
///
|
|
/// * [SliverAppBar] for more animated examples of how this property changes the
|
|
/// behavior of the app bar in combination with [pinned] and [floating].
|
|
final bool snap;
|
|
|
|
/// Whether the app bar should stretch to fill the over-scroll area.
|
|
///
|
|
/// The app bar can still expand and contract as the user scrolls, but it will
|
|
/// also stretch when the user over-scrolls.
|
|
final bool stretch;
|
|
|
|
/// The offset of overscroll required to activate [onStretchTrigger].
|
|
///
|
|
/// This defaults to 100.0.
|
|
final double stretchTriggerOffset;
|
|
|
|
/// The callback function to be executed when a user over-scrolls to the
|
|
/// offset specified by [stretchTriggerOffset].
|
|
final AsyncCallback? onStretchTrigger;
|
|
|
|
/// {@macro flutter.material.appbar.toolbarHeight}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final double toolbarHeight;
|
|
|
|
/// {@macro flutter.material.appbar.leadingWidth}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final double? leadingWidth;
|
|
|
|
/// {@macro flutter.material.appbar.backwardsCompatibility}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
@Deprecated(
|
|
'This property is obsolete and is false by default. '
|
|
'This feature was deprecated after v2.4.0-0.0.pre.',
|
|
)
|
|
final bool? backwardsCompatibility;
|
|
|
|
/// {@macro flutter.material.appbar.toolbarTextStyle}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final TextStyle? toolbarTextStyle;
|
|
|
|
/// {@macro flutter.material.appbar.titleTextStyle}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final TextStyle? titleTextStyle;
|
|
|
|
/// {@macro flutter.material.appbar.systemOverlayStyle}
|
|
///
|
|
/// This property is used to configure an [AppBar].
|
|
final SystemUiOverlayStyle? systemOverlayStyle;
|
|
|
|
@override
|
|
State<TranslucentSliverAppBar> createState() => _SliverAppBarState();
|
|
}
|
|
|
|
class _SliverAppBarState extends State<TranslucentSliverAppBar>
|
|
with TickerProviderStateMixin {
|
|
FloatingHeaderSnapConfiguration? _snapConfiguration;
|
|
OverScrollHeaderStretchConfiguration? _stretchConfiguration;
|
|
PersistentHeaderShowOnScreenConfiguration? _showOnScreenConfiguration;
|
|
|
|
void _updateSnapConfiguration() {
|
|
if (widget.snap && widget.floating) {
|
|
_snapConfiguration = FloatingHeaderSnapConfiguration(
|
|
curve: Curves.easeOut,
|
|
duration: const Duration(milliseconds: 200),
|
|
);
|
|
} else {
|
|
_snapConfiguration = null;
|
|
}
|
|
|
|
_showOnScreenConfiguration = widget.floating & widget.snap
|
|
? const PersistentHeaderShowOnScreenConfiguration(
|
|
minShowOnScreenExtent: double.infinity)
|
|
: null;
|
|
}
|
|
|
|
void _updateStretchConfiguration() {
|
|
if (widget.stretch) {
|
|
_stretchConfiguration = OverScrollHeaderStretchConfiguration(
|
|
stretchTriggerOffset: widget.stretchTriggerOffset,
|
|
onStretchTrigger: widget.onStretchTrigger,
|
|
);
|
|
} else {
|
|
_stretchConfiguration = null;
|
|
}
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_updateSnapConfiguration();
|
|
_updateStretchConfiguration();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(TranslucentSliverAppBar oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (widget.snap != oldWidget.snap || widget.floating != oldWidget.floating)
|
|
_updateSnapConfiguration();
|
|
if (widget.stretch != oldWidget.stretch) _updateStretchConfiguration();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
assert(!widget.primary || debugCheckHasMediaQuery(context));
|
|
final double bottomHeight = widget.bottom?.preferredSize.height ?? 0.0;
|
|
final double topPadding =
|
|
widget.primary ? MediaQuery.of(context).padding.top : 0.0;
|
|
final double collapsedHeight =
|
|
(widget.pinned && widget.floating && widget.bottom != null)
|
|
? (widget.collapsedHeight ?? 0.0) + bottomHeight + topPadding
|
|
: (widget.collapsedHeight ?? widget.toolbarHeight) +
|
|
bottomHeight +
|
|
topPadding;
|
|
|
|
return MediaQuery.removePadding(
|
|
context: context,
|
|
removeBottom: true,
|
|
child: SliverPersistentHeader(
|
|
floating: widget.floating,
|
|
pinned: widget.pinned,
|
|
delegate: _SliverAppBarDelegate(
|
|
vsync: this,
|
|
leading: widget.leading,
|
|
automaticallyImplyLeading: widget.automaticallyImplyLeading,
|
|
title: widget.title,
|
|
actions: widget.actions,
|
|
flexibleSpace: widget.flexibleSpace,
|
|
bottom: widget.bottom,
|
|
elevation: widget.elevation,
|
|
shadowColor: widget.shadowColor,
|
|
surfaceTintColor: widget.surfaceTintColor,
|
|
forceElevated: widget.forceElevated,
|
|
backgroundColor: widget.backgroundColor,
|
|
scrolledUnderBackgroundColor: widget.scrolledUnderBackgroundColor,
|
|
foregroundColor: widget.foregroundColor,
|
|
brightness: widget.brightness,
|
|
iconTheme: widget.iconTheme,
|
|
actionsIconTheme: widget.actionsIconTheme,
|
|
textTheme: widget.textTheme,
|
|
primary: widget.primary,
|
|
centerTitle: widget.centerTitle,
|
|
excludeHeaderSemantics: widget.excludeHeaderSemantics,
|
|
titleSpacing: widget.titleSpacing,
|
|
expandedHeight: widget.expandedHeight,
|
|
collapsedHeight: collapsedHeight,
|
|
topPadding: topPadding,
|
|
floating: widget.floating,
|
|
pinned: widget.pinned,
|
|
shape: widget.shape,
|
|
snapConfiguration: _snapConfiguration,
|
|
stretchConfiguration: _stretchConfiguration,
|
|
showOnScreenConfiguration: _showOnScreenConfiguration,
|
|
toolbarHeight: widget.toolbarHeight,
|
|
leadingWidth: widget.leadingWidth,
|
|
backwardsCompatibility: widget.backwardsCompatibility,
|
|
toolbarTextStyle: widget.toolbarTextStyle,
|
|
titleTextStyle: widget.titleTextStyle,
|
|
systemOverlayStyle: widget.systemOverlayStyle,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
|
_SliverAppBarDelegate({
|
|
required this.leading,
|
|
required this.automaticallyImplyLeading,
|
|
required this.title,
|
|
required this.actions,
|
|
required this.flexibleSpace,
|
|
required this.bottom,
|
|
required this.elevation,
|
|
required this.shadowColor,
|
|
required this.surfaceTintColor,
|
|
required this.forceElevated,
|
|
required this.backgroundColor,
|
|
required this.scrolledUnderBackgroundColor,
|
|
required this.foregroundColor,
|
|
required this.brightness,
|
|
required this.iconTheme,
|
|
required this.actionsIconTheme,
|
|
required this.textTheme,
|
|
required this.primary,
|
|
required this.centerTitle,
|
|
required this.excludeHeaderSemantics,
|
|
required this.titleSpacing,
|
|
required this.expandedHeight,
|
|
required this.collapsedHeight,
|
|
required this.topPadding,
|
|
required this.floating,
|
|
required this.pinned,
|
|
required this.vsync,
|
|
required this.snapConfiguration,
|
|
required this.stretchConfiguration,
|
|
required this.showOnScreenConfiguration,
|
|
required this.shape,
|
|
required this.toolbarHeight,
|
|
required this.leadingWidth,
|
|
required this.backwardsCompatibility,
|
|
required this.toolbarTextStyle,
|
|
required this.titleTextStyle,
|
|
required this.systemOverlayStyle,
|
|
}) : assert(primary || topPadding == 0.0),
|
|
assert(
|
|
!floating ||
|
|
(snapConfiguration == null &&
|
|
showOnScreenConfiguration == null) ||
|
|
vsync != null,
|
|
'vsync cannot be null when snapConfiguration or showOnScreenConfiguration is not null, and floating is true',
|
|
),
|
|
_bottomHeight = bottom?.preferredSize.height ?? 0.0;
|
|
|
|
final Widget? leading;
|
|
final bool automaticallyImplyLeading;
|
|
final Widget? title;
|
|
final List<Widget>? actions;
|
|
final Widget? flexibleSpace;
|
|
final PreferredSizeWidget? bottom;
|
|
final double? elevation;
|
|
final Color? shadowColor;
|
|
final Color? surfaceTintColor;
|
|
final bool forceElevated;
|
|
final Color? backgroundColor;
|
|
final Color? scrolledUnderBackgroundColor;
|
|
final Color? foregroundColor;
|
|
final Brightness? brightness;
|
|
final IconThemeData? iconTheme;
|
|
final IconThemeData? actionsIconTheme;
|
|
final TextTheme? textTheme;
|
|
final bool primary;
|
|
final bool? centerTitle;
|
|
final bool excludeHeaderSemantics;
|
|
final double? titleSpacing;
|
|
final double? expandedHeight;
|
|
final double collapsedHeight;
|
|
final double topPadding;
|
|
final bool floating;
|
|
final bool pinned;
|
|
final ShapeBorder? shape;
|
|
final double? toolbarHeight;
|
|
final double? leadingWidth;
|
|
final bool? backwardsCompatibility;
|
|
final TextStyle? toolbarTextStyle;
|
|
final TextStyle? titleTextStyle;
|
|
final SystemUiOverlayStyle? systemOverlayStyle;
|
|
final double _bottomHeight;
|
|
|
|
@override
|
|
double get minExtent => collapsedHeight;
|
|
|
|
@override
|
|
double get maxExtent => math.max(
|
|
topPadding +
|
|
(expandedHeight ?? (toolbarHeight ?? kToolbarHeight) + _bottomHeight),
|
|
minExtent);
|
|
|
|
@override
|
|
final TickerProvider vsync;
|
|
|
|
@override
|
|
final FloatingHeaderSnapConfiguration? snapConfiguration;
|
|
|
|
@override
|
|
final OverScrollHeaderStretchConfiguration? stretchConfiguration;
|
|
|
|
@override
|
|
final PersistentHeaderShowOnScreenConfiguration? showOnScreenConfiguration;
|
|
|
|
@override
|
|
Widget build(
|
|
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
|
final double visibleMainHeight = maxExtent - shrinkOffset - topPadding;
|
|
final double extraToolbarHeight = math.max(
|
|
minExtent -
|
|
_bottomHeight -
|
|
topPadding -
|
|
(toolbarHeight ?? kToolbarHeight),
|
|
0.0);
|
|
final double visibleToolbarHeight =
|
|
visibleMainHeight - _bottomHeight - extraToolbarHeight;
|
|
|
|
final bool isScrolledUnder =
|
|
overlapsContent || (pinned && shrinkOffset > maxExtent - minExtent);
|
|
final bool isPinnedWithOpacityFade =
|
|
pinned && floating && bottom != null && extraToolbarHeight == 0.0;
|
|
final double toolbarOpacity = !pinned || isPinnedWithOpacityFade
|
|
? (visibleToolbarHeight / (toolbarHeight ?? kToolbarHeight))
|
|
.clamp(0.0, 1.0)
|
|
: 1.0;
|
|
|
|
final Widget appBar = FlexibleSpaceBar.createSettings(
|
|
minExtent: minExtent,
|
|
maxExtent: maxExtent,
|
|
currentExtent: math.max(minExtent, maxExtent - shrinkOffset),
|
|
toolbarOpacity: toolbarOpacity,
|
|
isScrolledUnder: isScrolledUnder,
|
|
child: Stack(
|
|
children: [
|
|
SizedBox(
|
|
width: double.infinity,
|
|
height: math.max(minExtent, maxExtent - shrinkOffset),
|
|
child: ClipRect(
|
|
child: BackdropFilter(
|
|
filter: Theme.of(context).appBarBlurFilter,
|
|
child: const ColoredBox(
|
|
color: Colors.transparent,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
AppBar(
|
|
leading: leading,
|
|
automaticallyImplyLeading: automaticallyImplyLeading,
|
|
title: title,
|
|
actions: actions,
|
|
flexibleSpace: (title == null &&
|
|
flexibleSpace != null &&
|
|
!excludeHeaderSemantics)
|
|
? Semantics(
|
|
header: true,
|
|
child: flexibleSpace,
|
|
)
|
|
: flexibleSpace,
|
|
bottom: bottom,
|
|
elevation: forceElevated || isScrolledUnder ? elevation : 0.0,
|
|
scrolledUnderElevation: 0,
|
|
shadowColor: shadowColor,
|
|
surfaceTintColor: surfaceTintColor,
|
|
backgroundColor: isScrolledUnder
|
|
? scrolledUnderBackgroundColor
|
|
: backgroundColor,
|
|
foregroundColor: foregroundColor,
|
|
brightness: brightness,
|
|
iconTheme: iconTheme,
|
|
actionsIconTheme: actionsIconTheme,
|
|
textTheme: textTheme,
|
|
primary: primary,
|
|
centerTitle: centerTitle,
|
|
excludeHeaderSemantics: excludeHeaderSemantics,
|
|
titleSpacing: titleSpacing,
|
|
shape: shape,
|
|
toolbarOpacity: toolbarOpacity,
|
|
bottomOpacity: pinned
|
|
? 1.0
|
|
: ((visibleMainHeight / _bottomHeight).clamp(0.0, 1.0)),
|
|
toolbarHeight: toolbarHeight,
|
|
leadingWidth: leadingWidth,
|
|
backwardsCompatibility: backwardsCompatibility,
|
|
toolbarTextStyle: toolbarTextStyle,
|
|
titleTextStyle: titleTextStyle,
|
|
systemOverlayStyle: systemOverlayStyle,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
return appBar;
|
|
}
|
|
|
|
@override
|
|
bool shouldRebuild(covariant _SliverAppBarDelegate oldDelegate) {
|
|
return leading != oldDelegate.leading ||
|
|
automaticallyImplyLeading != oldDelegate.automaticallyImplyLeading ||
|
|
title != oldDelegate.title ||
|
|
actions != oldDelegate.actions ||
|
|
flexibleSpace != oldDelegate.flexibleSpace ||
|
|
bottom != oldDelegate.bottom ||
|
|
_bottomHeight != oldDelegate._bottomHeight ||
|
|
elevation != oldDelegate.elevation ||
|
|
shadowColor != oldDelegate.shadowColor ||
|
|
backgroundColor != oldDelegate.backgroundColor ||
|
|
scrolledUnderBackgroundColor !=
|
|
oldDelegate.scrolledUnderBackgroundColor ||
|
|
foregroundColor != oldDelegate.foregroundColor ||
|
|
brightness != oldDelegate.brightness ||
|
|
iconTheme != oldDelegate.iconTheme ||
|
|
actionsIconTheme != oldDelegate.actionsIconTheme ||
|
|
textTheme != oldDelegate.textTheme ||
|
|
primary != oldDelegate.primary ||
|
|
centerTitle != oldDelegate.centerTitle ||
|
|
titleSpacing != oldDelegate.titleSpacing ||
|
|
expandedHeight != oldDelegate.expandedHeight ||
|
|
topPadding != oldDelegate.topPadding ||
|
|
pinned != oldDelegate.pinned ||
|
|
floating != oldDelegate.floating ||
|
|
vsync != oldDelegate.vsync ||
|
|
snapConfiguration != oldDelegate.snapConfiguration ||
|
|
stretchConfiguration != oldDelegate.stretchConfiguration ||
|
|
showOnScreenConfiguration != oldDelegate.showOnScreenConfiguration ||
|
|
forceElevated != oldDelegate.forceElevated ||
|
|
toolbarHeight != oldDelegate.toolbarHeight ||
|
|
leadingWidth != oldDelegate.leadingWidth ||
|
|
backwardsCompatibility != oldDelegate.backwardsCompatibility ||
|
|
toolbarTextStyle != oldDelegate.toolbarTextStyle ||
|
|
titleTextStyle != oldDelegate.titleTextStyle ||
|
|
systemOverlayStyle != oldDelegate.systemOverlayStyle;
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return '${describeIdentity(this)}(topPadding: ${topPadding.toStringAsFixed(1)}, bottomHeight: ${_bottomHeight.toStringAsFixed(1)}, ...)';
|
|
}
|
|
}
|