web-dev-qa-db-ja.com

SliverPersistentHeaderを「overgrow」する方法

私はSliverPersistentHeaderCustomScrollViewを使用して、ユーザーがスクロールしたときに縮小および拡大する永続的なヘッダーを使用していますが、最大サイズに達すると、少し硬めに感じます「過成長」。

以下は、(Spotifyアプリから)欲しい動作と私が持っている動作のビデオです:

Video of behaviour

7
enyo

この問題は、カスタム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;
  }
}
1
etheman1111