18

For the last few days, I've been reading through flutter framework documentation and especially the sliver part but I'm not quite sure where to start. I'm trying to implement the sticky headers and snap effect. Might the RenderSliverList be a good start? Do I need to re-layout things? Do I need to do additional drawing? And if so where?

Any help on where to start would be a huge help, thanks in advance!

Edit: I think I understood the layout part now, but I just can't find where the painting is supposed to happen.

Edit 2: For clarification, this is the desired "sticky header effect":

How can I make sticky headers in RecyclerView? (Without external lib)

and this is the "snap" effect:

https://rubensousa.github.io/2016/08/recyclerviewsnap

4

6 回答 6

24

对于“粘头效果”,我自己也遇到了这个问题,所以我创建了这个包来管理带有条子的粘头:https ://github.com/letsar/flutter_sticky_header

颤振粘性标题

要使用它,您必须SliverStickyHeaderCustomScrollView.

一节可以这样写:

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,
    ),
  ),
);

如果需要,上述演示的完整源代码在这里:https ://github.com/letsar/flutter_sticky_header/blob/master/example/lib/main.dart

我希望这能帮到您。

于 2018-06-16T14:51:57.573 回答
14

这很简单:

使用 aCustomScrollView并将其作为孩子 aSliverList和 a SliverAppBar。如果需要,您可以SliverList用 a替换。SliverGrid

然后,根据您想要达到的效果,您可以设置一些属性SliverAppBar

  • 折断
  • 扩展高度(+灵活空间)
  • 漂浮的
  • 固定

最后,你可能会有类似的东西:

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'),
                    );
                },
            ),
        ),
    ],
)

更好的是,您可以在单个CustomScrollView. 这意味着您可以通过将 aSliverGrid作为子项添加到您的 scrollView 来潜在地拥有一个网格,然后是一个列表。

我知道我知道,颤振很棒。

于 2018-02-05T08:38:31.390 回答
10

我设法使用以下代码在 iOS 应用程序的 Flutter 上实现了 Stickyheader 效果 - 归功于我从这里获得灵感的这段代码(https://github.com/flutter/flutter/blob/master/示例/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;
  }
}

要使其具有粘性,请将 _SliverAppBarDelegate 添加到 silvers 小部件列表:

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

我不确定如何让 _SliverAppBarDelegate 包装内容,但我必须为其提供 36 个逻辑像素的大小才能使其正常工作。如果有人知道它如何包装内容,请在下面的答案中发表评论。

在此处输入图像描述

于 2018-04-15T19:26:34.337 回答
2

我解决了这个问题,试试sticky_and_expandable_list

在此处输入图像描述

特征

  • 支持构建可展开的 ListView,可以展开/折叠部分或创建粘性部分标题。
  • 与 CustomScrollView、SliverAppBar 一起使用。
  • 监听当前sticky header、当前sticky header index和switching header index的滚动偏移量。
  • 仅使用一个列表小部件,因此它支持大数据和小内存使用。更多section自定义支持,可以通过sectionBuilder返回一个新的section widget,自定义背景、展开/折叠动画、section布局等。
  • 支持添加分隔符。
于 2020-04-20T05:15:03.490 回答
0

使用Flutter Sticky Headers依赖项将标题放置在可滚动内容上,当内容滚动时,这些标题将粘在容器顶部。

您可以在任何可滚动内容中放置一个StickyHeader或,StickyHeaderBuilder例如:、、、ListView或类似内容。GridViewCustomScrollViewSingleChildScrollView

依赖它:

dependencies:
  sticky_headers: "^0.1.8"

导入它:

import 'package:sticky_headers/sticky_headers.dart';

用它:

class Example extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ListView.builder(itemBuilder: (context, index) {
      return StickyHeader(
        header: Container(
          height: 50.0,
          color: Colors.blueGrey[700],
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          alignment: Alignment.centerLeft,
          child: Text('Header #$index',
            style: const TextStyle(color: Colors.white),
          ),
        ),
        content: Container(
          child: Image.network(imageForIndex(index), fit: BoxFit.cover,
            width: double.infinity, height: 200.0),
        ),
      );
    });
  }
}

在此处输入图像描述

于 2021-01-10T05:42:59.547 回答
0

根据文档,您可以在任何可滚动内容中放置一个StickyHeader或。StickyHeaderBuilder

文档页面仅提供了一个示例如何应用 aStickyHeader和 a ListView,那么其他小部件(例如SingleChildScrollVieworCustomScrollView呢?

在这个例子中,我将提供一个非常简单StickyHeader的 aSingleChildScrollView并且确保你可以将它放在任何SingleChildScrollView你想要的里面:

return Container(
    child: SingleChildScrollView(
      scrollDirection: Axis.vertical,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("My title"),
          StickyHeader(
            header: Container(
                  child: // Put here whatever widget you like as the sticky widget
                ),
            content: Column(
              children: [
                Container(
                  child: // Put here whatever widget you like as scrolling content (Column, Text, ListView, etc...)
                ),
              ],
            ),
          ),
        ],
      ),
    ),
  );
于 2021-12-29T10:00:08.753 回答