SliverList中的分隔符/分割线在Flutter中是什么?

23

我们如何在SliverList中实现分隔符/分割线。ListView.separated是在列表中创建分隔符的方便方法,但我没有看到任何关于SliverList的文档或示例。

6个回答

51

与 ListView.separated 类似

  import 'dart:math' as math;

  List<String> values = List();
  for (int i = 1; i <= 50; i++) {
    values.add(i.toString());
  }

  return CustomScrollView(
    semanticChildCount: values.length,
    slivers: <Widget>[
      SliverList(
        delegate: SliverChildBuilderDelegate(
          (BuildContext context, int index) {
            final int itemIndex = index ~/ 2;
            if (index.isEven) {
              return Padding(
                  child: Text(values[itemIndex]),
                  padding: EdgeInsets.all(16));
            }
            return Divider(height: 0, color: Colors.grey);
          },
          semanticIndexCallback: (Widget widget, int localIndex) {
            if (localIndex.isEven) {
              return localIndex ~/ 2;
            }
            return null;
          },
          childCount: math.max(0, values.length * 2 - 1),
        ),
      ),
    ],
  );

好的,这段代码可行,顺便说句谢谢,但是我不太理解大部分内容,比如为什么要除以2并检查偶数,我有点迷惑,如果您能简要解释一下这里发生了什么,我会很感激。 - lulliezy
1
因为SliverChildBuilderDelegate为每个项目构建了一个额外的小部件(Divider)。您可以看到原始列表(values)有50个项目。现在,您需要为每个项目构建一个额外的Divider,忽略最后一个(即49个以上的分隔符): values.length * 2 - 1。例如,您的原始列表[item1,item2,item3]将变为[item1,divider,item2,divider,item3]。在构建中,您检查新索引是否表示项目或分隔符:[0-item1-even,1-divider-odd,2-item2-even,3-divider-odd,4-item3-even]。 - Carlos Eduardo
1
当然,你可以忽略所有这些,通过在Column中添加divider来构建单个Widget。你只需要关注列表中的最后一个,或者不关注... - Carlos Eduardo

11

简单的方法,

使用 SliverFillRemaining

return CustomScrollView(
    slivers: <Widget>[
      SliverFillRemaining(
        child: ListView.separated(
            itemCount:value.length,
            //shrinkWrap: true,
            physics: NeverScrollableScrollPhysics(),
            //padding: EdgeInsets.all(0),
            separatorBuilder: (BuildContext context, int index){
              return Divider();
            },
            itemBuilder: (BuildContext context, int index) {
              //widget return
            })
      ),
使用SliverList
 SliverList(
            delegate: SliverChildBuilderDelegate(
                  (BuildContext context, int index) {
                return Column(
                  children: <Widget>[
                    SizedBox(height: 5),
                    //your main widget is here
                    SizedBox(height: 5),
                    Divider(height: 1)
                  ],
                );

              },
              childCount: model.length,
            ),
          )

7
请注意:除非别无选择,请不要使用第一种方法。这将一次性渲染所有子代,可能导致巨大的内存问题和可怕的用户体验。 - Christian X
@ChristianX 不使用 shrinkWrap: true 会尝试渲染列表中的所有项,即使不在视口中吗?这难道不会抵消 SliverFillremaining 的效果吗? - Nithin Sai
我不这么认为,因为据我所知,sliverfillremaining只会给列表一个固定的高度。可能我错了,但我已经使用这个小部件有一段时间了。 - Christian X
*havent worked... - Christian X
感谢您提供的SliverFillRemaining技巧。 - Sergio Tskhovrebov

6

虽然这个问题很旧,但我会为未来的读者添加我的答案。 你可以简单地用 Container 包装你的小部件,然后给容器一个底部边框。以下是一个示例:

Container(
    decoration: BoxDecoration(
        border: Border(
            bottom: BorderSide(color: Colors.grey.shade300, width: 0.5))),
    child: YourWidget(),
  ),

太棒了。我从未想过我们可以使用容器实现这一点。 - dante

2
如果你想展示分割线但是不想在最后一个项目上显示,可以尝试以下方法。将你的小部件包装在Column中,然后为构建分割线提供条件。分割线小部件将会在除了最后一个索引以外的地方显示。例如:
CustomScrollView(
  slivers: <Widget>[
    SliverList(
      delegate: SliverChildBuilderDelegate(
        (_, int index) {
          return Column(
            children: <Widget>[
              // Put your widget here
              YourWidget(),

              // This divider will not appears on last index
              if(index != (item.length - 1))
                const Divider(),
            ],
          );
        },
        childCount: item.length,
      ),
    ),
  ],
),

我很好奇这样做是否会影响性能。 - Eng

2
在slivers中使用SliverList.separated

-11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接