私はSliverPersistentHeader
でCustomScrollView
を使用して、ユーザーがスクロールしたときに縮小および拡大する永続的なヘッダーを使用していますが、最大サイズに達すると、少し硬めに感じます「過成長」。
以下は、(Spotifyアプリから)欲しい動作と私が持っている動作のビデオです:
。
この問題は、カスタムSliverPersistentHeaderDelegate
を作成するだけで解決しました。
StretchConfigurationのゲッターをオーバーライドするだけです。これが便利な場合の私のコードは次のとおりです。
class LargeCustomHeader extends SliverPersistentHeaderDelegate {
LargeCustomHeader(
{this.children,
this.title = '',
this.childrenHeight = 0,
this.backgroundImage,
this.titleHeight = 44,
this.titleMaxLines = 1,
this.titleTextStyle = const TextStyle(
fontSize: 30,
letterSpacing: 0.5,
fontWeight: FontWeight.bold,
height: 1.2,
color: ColorConfig.primaryContrastColor)}) {}
final List<Widget> children;
final String title;
final double childrenHeight;
final String backgroundImage;
final int _fadeDuration = 250;
final double titleHeight;
final int titleMaxLines;
final double _navBarHeight = 56;
final TextStyle titleTextStyle;
@override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return Container(
constraints: BoxConstraints.expand(),
decoration: BoxDecoration(
// borderRadius: BorderRadius.vertical(bottom: Radius.circular(35.0)),
color: Colors.black,
),
child: Stack(
fit: StackFit.loose,
children: <Widget>[
if (this.backgroundImage != null) ...[
Positioned(
top: 0,
left: 0,
right: 0,
bottom: 0,
child: FadeInImage.assetNetwork(
placeholder: "assets/images/image-placeholder.png",
image: backgroundImage,
placeholderScale: 1,
fit: BoxFit.cover,
alignment: Alignment.center,
imageScale: 0.1,
fadeInDuration: const Duration(milliseconds: 500),
fadeOutDuration: const Duration(milliseconds: 200),
),
),
Positioned(
top: 0,
left: 0,
right: 0,
bottom: 0,
child: Container(
color: Color.fromRGBO(0, 0, 0, 0.6),
),
),
],
Positioned(
bottom: 0,
left: 0,
right: 0,
top: _navBarHeight + titleHeight,
child: AnimatedOpacity(
opacity: (shrinkOffset >= childrenHeight / 3) ? 0 : 1,
duration: Duration(milliseconds: _fadeDuration),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[if (children != null) ...children],
))),
Positioned(
top: _navBarHeight,
left: 0,
right: 0,
height: titleHeight,
child: Padding(
padding: const EdgeInsets.only(
right: 30, bottom: 0, left: 30, top: 5),
child: AnimatedOpacity(
opacity: (shrinkOffset >= childrenHeight + (titleHeight / 3))
? 0
: 1,
duration: Duration(milliseconds: _fadeDuration),
child: Text(
title,
style: titleTextStyle,
maxLines: titleMaxLines,
overflow: TextOverflow.Ellipsis,
),
),
),
),
Container(
color: Colors.transparent,
height: _navBarHeight,
child: AppBar(
elevation: 0.0,
backgroundColor: Colors.transparent,
title: AnimatedOpacity(
opacity:
(shrinkOffset >= childrenHeight + (titleHeight / 3))
? 1
: 0,
duration: Duration(milliseconds: _fadeDuration),
child: Text(
title,
),
)),
)
],
));
}
@override
double get maxExtent => _navBarHeight + titleHeight + childrenHeight;
@override
double get minExtent => _navBarHeight;
// @override
// FloatingHeaderSnapConfiguration get snapConfiguration => FloatingHeaderSnapConfiguration() ;
@override
OverScrollHeaderStretchConfiguration get stretchConfiguration =>
OverScrollHeaderStretchConfiguration(
stretchTriggerOffset: maxExtent,
onStretchTrigger: () {},
);
double get maxShrinkOffset => maxExtent - minExtent;
@override
bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) {
//TODO: implement specific rebuild checks
return true;
}
}