隐藏顶部标题,直到滚动到特定高度

时间:2019-11-23 00:56:47

标签: flutter flutter-layout

我是扑朔迷离的新手,我想实现这样的功能:(klook应用)

Klook scroll

基本上,这是当用户滚动一点时显示的按钮。

我使用SliverAppBar和SliverStickyHeader尝试了不同的操作,但是我无法使其工作。我还玩过“不透明度和可见性”,但是它可以移动我的洞视图,并且不会“重叠”我的横幅/搜索控件。

到目前为止,我的代码:

class _ExplorePageState extends State<ExplorePage> {
  ScrollController _scrollController;
  bool lastStatus = true;

  _scrollListener() {
    if (isShrink != lastStatus) {
      print("listen");
      setState(() {
        lastStatus = isShrink;
      });
    }
  }

  bool get isShrink {
    return _scrollController.hasClients &&
        _scrollController.offset > (400 - kToolbarHeight);
  }

  @override
  void initState() {
    _scrollController = ScrollController();
    _scrollController.addListener(_scrollListener);
    super.initState();
  }

  @override
  void dispose() {
    _scrollController.removeListener(_scrollListener());
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        controller: _scrollController,
        slivers: <Widget>[
          SliverStickyHeader(
            header: Visibility(
              child: Container(
                color: Colors.red,
                height: isShrink ? 100 : 0,
                child: Text('Header 1'),
              ),
              visible: isShrink ? true : false,
              maintainState: true,
              maintainSize: true,
              maintainAnimation: true,
            ),
            sliver: SliverList(
              delegate: SliverChildListDelegate(
                [
                  BannerWidget(),
                  ButtonWidget(),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

BannerWidget和ButtomWidget是类似于上面显示的应用程序的两个容器。

我希望您能帮助我,或者告诉我这种行为的含义。 谢谢!

1 个答案:

答案 0 :(得分:0)

如果可以使用CustomScrollView,可以将SliverPersistentHeader与自己的委托一起使用。它将允许您访问当前的页眉滚动状态,并根据剩余的空间进行自己的布局。

demo

const double _kSearchHeight = 50.0;
const double _kHeaderHeight = 250.0;

class _ExplorePageState extends State<ExplorePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: CustomScrollView(
          slivers: <Widget>[
            SliverPersistentHeader(
              delegate: DelegateWithSearchBar(),
              pinned: true,
            ),
            SliverList(
              delegate: SliverChildListDelegate(
                [
                  for (int i = 0; i < 4; i++) 
                    Container(
                      height: 200,
                      child: Text('test'),
                      color: Colors.black26
                    ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

class DelegateWithSearchBar extends SliverPersistentHeaderDelegate {
  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    final showSearchBar = shrinkOffset > _kHeaderHeight - _kSearchHeight;

    return Stack(
      children: <Widget>[
        AnimatedOpacity(
          opacity: !showSearchBar ? 1 : 0,
          duration: Duration(milliseconds: 100),
          child: LayoutBuilder(
            builder: (context, constraints) {
              return Container(
                decoration: BoxDecoration(
                  image: DecorationImage(
                    image: NetworkImage('xxx'),
                    fit: BoxFit.cover
                  )
                ),
                height: constraints.maxHeight,
                child: SafeArea(
                  child: Container(
                    padding: EdgeInsets.only(left: 20, bottom: 20),
                    alignment: Alignment.bottomLeft,
                    child: Text(
                      'Sample Text',
                      style: TextStyle(color: Colors.white, fontSize: 22)
                    ),
                  ),
                ),
              );
            }
          ),
        ),
        AnimatedOpacity(
          opacity: showSearchBar ? 1 : 0,
          duration: Duration(milliseconds: 100),
          child: Container(
            height: _kSearchHeight,
            color: Colors.white,
            alignment: Alignment.center,
            child: Text('search bar')
          ),
        ),
      ],
    );
  }

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate _) => true;

  @override
  double get maxExtent => _kHeaderHeight;

  @override
  double get minExtent => _kSearchHeight;
}