【问题标题】:Flutter : How can I add divider between each List Item in my code?Flutter:如何在代码中的每个列表项之间添加分隔符?
【发布时间】:2018-11-14 04:55:36
【问题描述】:

如何在列表中添加分隔符?我使用 Flutter for Android。我想在每个列表项之间添加一个分隔线,我想为分隔线着色并添加样式。

我尝试添加new divider();,但出现错误。我也试过return new divider();

这是我的应用程序的屏幕截图:

这是我的代码:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
          primarySwatch: Colors.purple,

          buttonTheme: const ButtonThemeData(
            textTheme: ButtonTextTheme.primary,
          )
      ),
      home: const MyHomePage(),
    );
  }
}

class Kitten {
  const Kitten({this.name, this.description, this.age, this.imageurl});

  final String name;
  final String description;
  final int age;
  final String imageurl;
}

final List<Kitten> _kittens = <Kitten>[
  Kitten(
      name: "kitchen",
      description: "mehraboon",
      age: 2,
      imageurl:
      "https://images.pexels.com/photos/104827/cat-pet-animal-domestic- 
      104827.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=350",
  ),
  Kitten(
      name: "garage",
      description: "khashen",
      age: 1,
      imageurl:
      "https://images.pexels.com/photos/4602/jumping-cute-playing-animals.jpg? 
      auto=compress&cs=tinysrgb&dpr=2&h=350",
  ),
  Kitten(
      name: "bedroom",
      description: "khar zoor",
      age: 5,
      imageurl:
      "https://images.pexels.com/photos/978555/pexels-photo-978555.jpeg? 
      auto=compress&cs=tinysrgb&dpr=2&h=350",
  ),
  Kitten(
      name: "living room",
      description: "chorto",
      age: 3,
      imageurl:
      "https://images.pexels.com/photos/209037/pexels-photo-209037.jpeg? 
      auto=compress&cs=tinysrgb&dpr=2&h=350",
  ),
];

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key key}) : super(key: key);

  Widget _dialogBuilder(BuildContext context, Kitten kitten) {
    return SimpleDialog(contentPadding: EdgeInsets.zero, children: [
      Image.network(kitten.imageurl, fit: BoxFit.fill),
      Padding(
          padding: const EdgeInsets.all(16.0),
          child:
          Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
            Text(kitten.name),
            Text('${kitten.age}'),
            SizedBox(
              height: 16.0,
            ),
            Text(kitten.description),
            Align(
              alignment: Alignment.centerRight,
              child: Wrap(
                children: [
                  FlatButton(onPressed: () {}, child: const
                  Text("noooo!"),color: Colors.red,),
                  Padding(padding: const EdgeInsets.all(2.0),),
                  RaisedButton(onPressed: () {}, child: const
                  Text("yesss!"),color: Colors.green)
                ],
              ),
            )
          ]))
    ]);
  }

  Widget _listItemBuilder(BuildContext context, int index) {
    return new GestureDetector(

      onTap: () => showDialog(
          context: context,
          builder: (context) => _dialogBuilder(context, _kittens[index])),
      child:
      Container(

        padding: EdgeInsets.all( 16.0),
        alignment: Alignment.centerLeft,
        child: Text(_kittens[index].name,
            style: Theme.of(context).textTheme.headline),

      ),


    ) ;

  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Keys"),
        centerTitle: true,


      ),
      body: ListView.builder(
        itemCount: _kittens.length,
        itemExtent: 60.0,
        itemBuilder: _listItemBuilder,

      ),
    );
  }
}
 

【问题讨论】:

标签: android ios flutter


【解决方案1】:

有很多方法可以做同样的事情。让我在这里比较一下。

对于一个简短的静态列表

使用ListTile.divideTiles

ListView(
  children: ListTile.divideTiles( //          <-- ListTile.divideTiles
      context: context,
      tiles: [
        ListTile(
          title: Text('Horse'),
        ),
        ListTile(
          title: Text('Cow'),
        ),
        ListTile(
          title: Text('Camel'),
        ),
        ListTile(
          title: Text('Sheep'),
        ),
        ListTile(
          title: Text('Goat'),
        ),
      ]
  ).toList(),
)

对于长动态列表

使用ListView.separated

ListView.separated(
  itemCount: 100,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text('$index sheep'),
    );
  },
  separatorBuilder: (context, index) {
    return Divider();
  },
)

这会为每个项目返回两个小部件,最后一个项目除外。 separatorBuilder 用于添加分隔符。

用于在最后一项之后添加分隔符

创建一个使用 Divider 或 BoxDecoration 的自定义项目小部件。

使用分隔符

final items = ['Horse', 'Cow', 'Camel', 'Sheep', 'Goat'];

@override
Widget build(BuildContext context) {
  return ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, index) {
      return Column(
        children: <Widget>[
          ListTile(
            title: Text(items[index]),
          ),
          Divider(), //                           <-- Divider
        ],
      );
    },
  );
}

使用 BoxDecoration

final items = ['Horse', 'Cow', 'Camel', 'Sheep', 'Goat'];

@override
Widget build(BuildContext context) {
  return ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, index) {
      return Container(
        decoration: BoxDecoration( //                    <-- BoxDecoration
          border: Border(bottom: BorderSide()),
        ),
        child: ListTile(
          title: Text(items[index]),
        ),
      );
    },
  );
}

Divider 和 BoxDecoration 都可以根据行高和颜色进行自定义。 Divider 也有一个缩进选项,但你可以让 BoxDecoration 用一些填充来做同样的事情。

更多风格

使用卡片

final items = ['Horse', 'Cow', 'Camel', 'Sheep', 'Goat'];

@override
Widget build(BuildContext context) {
  return ListView.builder(
    itemCount: items.length,
    itemBuilder: (context, index) {
      return Card( //                           <-- Card
        child: ListTile(
          title: Text(items[index]),
        ),
      );
    },
  );
}

【讨论】:

  • 第一个项之前添加分隔符怎么样?
  • @AlexSemeniuk,您可以使用 Divider 或 BoxDecoration,类似于上面的示例。
  • 不幸的是,ListView.builderDivider 的示例禁用(隐藏)onTap 突出显示动画。
  • 完整答案!!谢谢!!
【解决方案2】:

最正确的方式是使用ListView.separated

ListView.separated(
     itemCount: 25,
     separatorBuilder: (BuildContext context, int index) => Divider(height: 1),
     itemBuilder: (BuildContext context, int index) {
       return ListTile(
         title: Text('item $index'),
       );
     },
);

【讨论】:

  • 提示 - 使用 Divider(height: 1) 删除默认填充
  • @JossefHarush 不错!
  • @JossefHarush 你救了我?
  • @TapasPal 随时:)。编辑答案并添加,因为与大多数用户相关
  • 另外,注意使用 ListView.separated last Item 不会有分隔符,您可以像这样显示它if (index == itemCount - 1) { return Divider(height: 1); }
【解决方案3】:

将您的小部件放入带有 BoxDecoration 的容器中

Container(
   child: YourWidgetHere(),
   decoration: BoxDecoration(
      border: Border(bottom: BorderSide(color: Colors.black26))),
);

【讨论】:

  • 这可以使用 Column 而不是 ListView。如果您不希望 ListView 中包含滚动条,这很有用。
【解决方案4】:

flutter getting started tutorial 上,他们提供的解决方案是这样的:

  body: ListView.builder(
    itemCount: _kittens.length,
    itemExtent: 60.0,
    itemBuilder: (context, i) {
        // Add a one-pixel-high divider widget before each row in theListView.
        if (i.isOdd) return new Divider(color: Colors.purple); // notice color is added to style divider

        return _listItemBuilder();
      },
  ),
  ...

这应该添加考虑到奇数行和偶数行的分隔符。

还要为分隔线着色,将“颜色”传递给Divider Class

new Divider(color: Colors.purple);

【讨论】:

  • 如果 itemCount 是 _kittens.length 并且您返回的所有其他项目都返回一个 Devider,您不会错过一半的小猫吗?入门教程与您的示例不同。
  • 隔板每两个添加一次,否则你会得到两个隔板,它们之间没有小猫。本教程确实涵盖了它,如我的回答中所示,但是他们添加了更多内容,但它不需要它来工作。当我对其进行测试时,效果很好。
  • 为此,您需要itemCount: _kittens.length * 2 否则是的,您错过了小猫的后半部分。
【解决方案5】:

最近我用这段代码来设置分隔符:

ListView.separated(
      itemBuilder: (BuildContext context, int index) {
        return ListTile(
          title: Text("Hello", style: TextStyle(
              color: Theme
                  .of(context)
                  .primaryColor
          ),),

        );
      },
      separatorBuilder: (context, index) =>Divider(height: 1, color: Colors.green),
      itemCount: 30),

它有效。

例如,我添加了我的应用的屏幕截图

【讨论】:

    【解决方案6】:

    看看这个问题: ListView.builder should let clients specify a divider 明确指出:

    1. 如果您需要使用动态元素构建列表,现在您必须自己处理这个问题。我建议在行小部件构建中,您在底部包含一个 List Divider 和一列或其他内容,除了最后一个(您可以测试 index == listData.length - 1)。

    2. 但是,如果像您展示的示例一样,您事先已经知道所有列表数据,或者您在没有ListView.builder 的情况下构建它,那么您可以并且应该使用命名构造函数ListView.divideTiles

    【讨论】:

      【解决方案7】:

      跟随this 只需添加 Divider() :

               Column(
                      children: <Widget>[
                        Container(
                          padding: EdgeInsets.all(16.0),
                          child: Column(
                            children: <Widget>[
                              Image.network(video["imageUrl"]),
                              Container(
                                height: 6.0,
                              ),
                              Text(
                                video["name"],
                                textScaleFactor: 1.05,
                                style: TextStyle(fontWeight: FontWeight.bold),
                              ),
                            ],
                          ),
                        ),
                        Divider(
                          color: Theme.of(context).primaryColor,
                        )
                      ],
                    );                                                                           
      

      【讨论】:

        【解决方案8】:

        飞镖 2.3

        另一种方法,特别是对于通用非列表视图:在集合中使用 for (link) 和 ... 扩展运算符

        Column(
           children: [
             for(var i=0; i<4; i+=1)
             ...[Container(height: 100, width: 100),
                 Divider()
              ]])
        

        【讨论】:

          【解决方案9】:

          这是使用 Container 的另一种方式。

           ListTile(
                  leading: Icon(Icons.home),
                  title: Text('Home'),
           ),
           Container(height: 1, color: Colors.grey), //divider
           ListTile(
                  leading: Icon(Icons.logout),
                  title: Text('Logout'),
           ),
          

          【讨论】:

            【解决方案10】:

            问题假设我们可以访问material.dart 以进行Android 样式设置(ListTileDivider)。如果您想要 Cupertino 风格,我们可以:

            1. 对行使用 Column 视图包装器,并添加高度为 1 的 Container

               Column(
                 children: <Widget>[
                   row, // A custom Row
                   Padding(
                     padding: const EdgeInsets.only(
                       left: 16,  // Adjust separator left padding.
                       right: 16, // Adjust separator right padding.
                     ),
                     child: Container(
                       height: 1,
                       color: Styles.productRowDivider, // Custom style
                     ),
                   ),
                 ],
               );
              
            2. Dividercupertino.dart 中不可用。我们可以使用与ListView.separated 相同的Container 技术:

               ListView.separated(
                 itemCount: 100,
                 itemBuilder: (context, index) {
                   return row;
                 },
                 separatorBuilder: (context, index) {
                   return Container(
                           height: 1,
                           color: Styles.productRowDivider, // Custom style
                         );
                 },
               );
              

            【讨论】:

            • material.dartcupertino.dart 可以同时导入,Divider 只使用前者。这没有开销,因为摇树将确保只有使用的内容才会包含在发布中。
            • 是的。澄清一下,我的意思是我们需要 cupertino.dart 来进行 Cupertino 造型。
            【解决方案11】:

            像这样创建一个容器

            Container(height: 1, color: Colors.grey),
            

            并像这样添加您的 ListTile

             ListView.builder(
              itemCount: _feed.items.length,
              itemBuilder: (BuildContext context, int index) {
                final item = _feed.items[index];
            
                 return  Column(
                     children: <Widget>[
                  Container(height: 1, color: Colors.grey),  //Container for devider
                  ListTile(                                  //Your tile item
                  title: title(item.title),
                  subtitle: subtitle(item.pubDate),
                  leading: thumbnail(item.enclosure.url),
                  trailing: rightIcon(),
                  contentPadding: EdgeInsets.all(5.0),
                  onTap: () => openFeed(item.link),
                )]);
              },
            );
            

            现在你可以在我的截图中看到最终输出

            [1]:https://i.stack.imgur.com/EZuIg.jpg

            【讨论】:

            • 如果你要使用ListView.builder,不妨换成ListView.separated。这样,您可以在 separatorBuilder 上传递一个新的 IndexedWidgetBuilder 并在那里构建您的分隔线。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-03-29
            • 2013-12-19
            • 2019-10-29
            • 2015-12-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多