flutter implement sticky headers and the snap to item effect

偶尔善良 提交于 2019-12-02 17:43:23

For the "sticky header effect" I ran into this problem myself, so I created this package to manage sticky headers with slivers: https://github.com/letsar/flutter_sticky_header

To use it you have to create one SliverStickyHeader per section in a CustomScrollView.

One section can be wrote like this:

new SliverStickyHeader(
  header: new Container(
    height: 60.0,
    color: Colors.lightBlue,
    padding: EdgeInsets.symmetric(horizontal: 16.0),
    alignment: Alignment.centerLeft,
    child: new Text(
      'Header #0',
      style: const TextStyle(color: Colors.white),
    ),
  ),
  sliver: new SliverList(
    delegate: new SliverChildBuilderDelegate(
      (context, i) => new ListTile(
            leading: new CircleAvatar(
              child: new Text('0'),
            ),
            title: new Text('List tile #$i'),
          ),
      childCount: 4,
    ),
  ),
);

If you want, the entire source code for the above demo is here: https://github.com/letsar/flutter_sticky_header/blob/master/example/lib/main.dart

I hope this will help you.

It's dead simple :

Use a CustomScrollView and give it as child both a SliverList and a SliverAppBar. You may replace the SliverList with a SliverGrid if you need to.

Then, depending on the effect you want to achieve, there are a few properties you may set on SliverAppBar:

  • snap
  • expandedHeight (+ flexibleSpace)
  • floating
  • pinned

In the end, you may have something similar to :

new CustomScrollView(
    slivers: <Widget>[
        new SliverAppBar(
            title: new Text("Title"),
            snap: true,
            floating: true,
        ),
        new SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: new SliverChildBuilderDelegate(
                (BuildContext context, int index) {
                    return new Container(
                        alignment: Alignment.center,
                        color: Colors.lightBlue[100 * (index % 9)],
                        child: new Text('list item $index'),
                    );
                },
            ),
        ),
    ],
)

Even better, you can concatenate different scroll behaviour inside a single CustomScrollView. Which means you can potentially have a grid followed by a list just by adding a SliverGrid as a child to your scrollView.

I know I know, flutter is awesome.

I managed to do the stickyheader effect on Flutter for an iOS app using the following code - credit goes to this piece of code written here from where I drew my inspiration (https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/animation/home.dart#L112):

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
    @required this.collapsedHeight,
    @required this.expandedHeight,}
      );

  final double expandedHeight;
  final double collapsedHeight;

  @override double get minExtent => collapsedHeight;
  @override double get maxExtent => math.max(expandedHeight, minExtent);

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new Container(color: Colors.red,
        child: new Padding(
          padding: const EdgeInsets.only(
              left: 8.0, top: 8.0, bottom: 8.0, right: 8.0),
          child: new Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              new Text("Time"), new Text("Price"), new Text("Hotness")
            ],
          ),
        )
    );
  }

  @override
  bool shouldRebuild(@checked _SliverAppBarDelegate oldDelegate) {
    return expandedHeight != oldDelegate.expandedHeight
        || collapsedHeight != oldDelegate.collapsedHeight;
  }
}

To make it sticky, add the _SliverAppBarDelegate to the silvers widget list:

 new SliverPersistentHeader(delegate: new _SliverAppBarDelegate(collapsedHeight: 36.0, expandedHeight: 36.0), pinned: true, ),

I'm not really sure how to make the _SliverAppBarDelegate wrap the content though, I had to provide it with a size of 36 logical pixels to get it to work. If anyone know how it could just wrap content, please drop a comment to the answer below.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!