带有分隔符的颤振组列表视图

Posted

技术标签:

【中文标题】带有分隔符的颤振组列表视图【英文标题】:Flutter group listviews with separator 【发布时间】:2018-04-24 07:09:34 【问题描述】:

我正在寻找一些指导来创建带有分隔符的列表视图。例如,我想从按日期分组的数据库中获取消息,并按日期用一些图形或线条等分隔消息……然后将消息放在分隔符下。在颤振中尝试这个,任何指导或推动正确的方向将不胜感激。

【问题讨论】:

另见Flutter divider: How could I add divider between each line in my code? 【参考方案1】:

我为设计的丑陋道歉,但只是为了向您展示,您几乎可以构建自己想要的设计,这是一个简单的示例:

import "package:flutter/material.dart";
import 'package:meta/meta.dart';

class Test extends StatefulWidget 
  @override
  _TestState createState() => new _TestState();


class _TestState extends State<Test> 
  @override
  Widget build(BuildContext context) 
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Test"),
      ),
      body: new ListView.builder(
        // itemCount: myData.lenght(),
          itemCount: 20,
          itemBuilder: (BuildContext context, int index) 
            //sort my data by timestamp before building
            return new CustomWidget(date: "Convert my time stamp to date",
              content: "My Awesome Content",
              trailingIconOne: new Icon(Icons.share, color: Colors.blueAccent,),
              trailingIconTwo: new Icon(
                Icons.favorite, color: Colors.redAccent,),);
          ),
    );
  


class CustomWidget extends StatelessWidget 
  String date;
  String content;

  Icon trailingIconOne;

  Icon trailingIconTwo;

  CustomWidget(
      @required this.date, @required this.content, @required this.trailingIconOne, @required this.trailingIconTwo);

  @override
  Widget build(BuildContext context) 
    return new Container(
      decoration: new BoxDecoration(
          border: new Border.all(color: Colors.grey[500])
      ),
      child: new Column(
        children: <Widget>[
          new Container (child: new Text(date), color: Colors.yellow[200],),
          new Container(height: 15.0,),
          new Text(content),
          new Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: <Widget>[
              new IconButton(icon: trailingIconOne, onPressed: () ),
              new Container(width: 10.0,),
              new IconButton(icon: trailingIconTwo, onPressed: () )
            ],
          )
        ],
      ),
    );
  

为了更好的设计,您可以去掉边框并改用Divider

return new Container(
      child: new Column(
        children: <Widget>[
          new Column (children: <Widget>[
            new Container (child: new Text(date), color: Colors.yellow[200],),
            new Container(height: 15.0,),
            new Text(content),
            new Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                new IconButton(icon: trailingIconOne, onPressed: () ),
                new Container(width: 10.0,),
                new IconButton(icon: trailingIconTwo, onPressed: () ),
          ], ),

              new Divider(height: 15.0,color: Colors.red,),
            ],
          )
        ],
      ),

我认为更好的视觉解决方案是使用Card而不是Container

return new Card(
      child: new Column(
        children: <Widget>[
          new Column (children: <Widget>[
            new Container (child: new Text(date), color: Colors.yellow[200],),
            new Container(height: 15.0,),
            new Text(content),
            new Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: <Widget>[
                new IconButton(icon: trailingIconOne, onPressed: () ),
                new Container(width: 10.0,),
                new IconButton(icon: trailingIconTwo, onPressed: () ),
          ], ),

            //  new Divider(height: 15.0,color: Colors.red,),
            ],
          )
        ],
      ),
    );

【讨论】:

谢谢,我认为这足以让我朝着正确的方向开始。如果我在路上遇到困难,我会发布一个新项目。 无论如何,我并不打算展示一个伟大的设计,是的,Divider 更好,但只是在这个特定的布局中,它需要调整才能产生效果。我在最后添加了更改,如果我们使用 Card 而不是 Container 作为父级,可能会更好看设计,但这个示例只是为了展示您可以自定义自己的小部件。 似乎我可以毫无问题地静态地做到这一点,我需要看到最好的方法是拉数据和排序。我是拉日期,然后在日期分隔符之后的每个小部件中拉出与该日期相关的消息,还是拉出所有数据并拉出我需要的日期的数据。我已经按照日期顺序将其作为单个列表视图完成,但希望转换为将特定日期的所有消息都放在分隔符下方。想法?还是我应该在这里问另一个问题以获得答案? 也许会问另一个问题以使其更清楚,通常您希望将时间戳存储在数据项本身中,我不确定这是否清楚。另一件事,如果您使用的是 Firebase rtdb,如果您的数据提取是分层的,则可以只使用 FirebaseAnimatedList 而不是 ListView,并且它提供了一个您可以使用的排序参数。 我正在使用 mysql 存储带有 JSON 字段的数据,并为可搜索和可索引字段生成列,这是客户对 DB 的要求。可能就像为唯一日期调用 restapi 一样容易,然后创建分隔符,然后调用数据,因为小部件是为该日期的消息列表视图构建的。如果我被阻止,我会创建一个问题。再次感谢【参考方案2】:

虽然这可能不适用于您的情况,但将分隔线添加到 ListView 的一种简单方法是使用 ListView.divideTiles

// Adapted from https://flutter.io/flutter-for-android/#listviews--adapters

import 'package:flutter/material.dart';

void main() 
  runApp(new MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new ListExamplePage(),
    );
  


class ListExamplePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // https://docs.flutter.io/flutter/material/ListTile/divideTiles.html
    var dividedWidgetList = ListTile.divideTiles(
        context: context,
        tiles: _getListData(),
        color: Colors.black).toList();

    return new Scaffold(
      appBar: new AppBar(
        title: new Text('List Example'),
      ),
      body: new ListView(children: dividedWidgetList)
    );
  

  _getListData() 
    List<Widget> widgets = [];
    for (int i=0; i<100; i++) 
      widgets.add(
        new Padding(
            padding: new EdgeInsets.all(10.0),
            child: new Text('Row $i'))
      );
    
    return widgets;
  

编辑:

对于动态构建的列表,ListTile.divideTiles 不是正确的选择。在构建列表项的阶段添加分隔符可能是最好的方法:

import 'package:flutter/material.dart';

void main() 
  runApp(new MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new ListExamplePage(),
    );
  


class ListExamplePage extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('List Example'),
        ),
        body: new ListView.builder(
          itemBuilder: (BuildContext context, int position) =>
              // Try using either _getRowWithDivider or _getRowWithBoxDecoration
              // for two different ways of rendering a divider
              _getRowWithDivider(position),
        ));
  

  /// Returns the widget at position i in the list, separated using a divider
  Widget _getRowWithDivider(int i) 
    var children = <Widget>[
      new Padding(padding: new EdgeInsets.all(10.0), child: new Text('Row $i')),
      new Divider(height: 5.0),
    ];

    return new Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: children,
    );
  

// Returns the widget at position i in the list, separated using a BoxDecoration
  Widget _getRowWithBoxDecoration(int i) 
    return new Container(
        decoration: new BoxDecoration(
            border:
                new Border(bottom: new BorderSide(color: Colors.grey[100]))),
        child: new Padding(
            padding: new EdgeInsets.all(10.0), child: new Text('Row $i')));
  

【讨论】:

这看起来很有希望,如果我通过 http 调用获取我的消息列表,你将如何继续,我将它放在一个列表中,现在我使用 listview.builder 并为每个项目应用一个小部件,但现在我想要一个按日期划分的分隔符,每个日期可以是 1 个或多个。我现在正在尝试做一个具有消息列表视图的分隔线列表视图,但与大小错误等作斗争。您的解决方案看起来更直接地接受日期所需的分隔线,而不是每个分隔线。任何建议都会很棒。 对于动态列表,很遗憾 ListTile.divideTiles 不适合您。我建议在构建每行小部件时使用 aziza 的建议并插入 Divider(或 BoxDecoration)。我将更新一个不同的代码 sn-p 来演示。【参考方案3】:

只需将ListItem 放入Container 并添加装饰:

  @override
  Widget build(BuildContext context) 
    return new Container(
        child: new ListTile(
          title: new Text('I have border')
        ),
        decoration:
            new BoxDecoration(
                border: new Border(
                    bottom: new BorderSide()
                )
            )
        );
  

【讨论】:

这更简洁,更容易理解,恕我直言 当然,但它会在最后一个元素的底部放置一个边框。这不是正确的做法。 @Tony 不一定“不是正确的做法”。如果 listtiles 被循环,检查是否最后一个索引,并且不显示边框。如果手动做listtile,不要在最后一项上添加边框。【参考方案4】:
final Iterable<ListTile> products = widget.products.map((Product product) 
  return productListAdapter(
    product: product,
  ).build(context);
);

final listView = ListTile.divideTiles(
        context: context, tiles: products, color: Colors.black12)
    .toList();

return ListView(
    padding: EdgeInsets.symmetric(vertical: 8.0), children: listView);

productListAdapter 代码在这里

class productListAdapter extends StatelessWidget 
   final Product product;  
   productListAdapter(this.product);

   TextStyle getTextStyle() 
       return TextStyle(
           fontSize: 16.0,
           color: Colors.black);
   

   Color getColor(BuildContext context) 
       return Theme.of(context).primaryColor;
     
   

   @override
   Widget build(BuildContext context) 
     return ListTile(
       title: Text(product.name),
       leading: CircleAvatar(
         child: Text(
           product.name[0],
           style: getTextStyle(),
         ),
         backgroundColor: getColor(context),
       ),
     );
   
 

【讨论】:

【参考方案5】:

一个更清洁和简单的解决方案是使用以下

ListView.separated(
  separatorBuilder: (context, index) => Divider(
        color: Colors.black,
      ),
  itemCount: 20,
  itemBuilder: (context, index) => Padding(
        padding: EdgeInsets.all(8.0),
        child: Center(child: Text("Index $index")),
      ),
)

【讨论】:

【参考方案6】:

这里有很多过于复杂的答案

只需使用divideTiles:

new ListView(
              children: ListTile.divideTiles(context: context, tiles:

或者使用分隔符:

new ListView.separated(
              itemCount: 25,
              separatorBuilder: (BuildContext context, int index) => Divider(),
              itemBuilder: (BuildContext context, int index) 

【讨论】:

ListView.builder 呢?【参考方案7】:

长答案短

只需使用Column 并添加Divider

ListView.builder(
      itemCount: count,
      itemBuilder: (context, int index) return tile(index);,
    ),

为 itemBuilder 创建一个小部件

Widget tile(int index) 
return Column(
  children: <Widget>[
    // your widgets in listView
    Divider(),    //at last simply add divider
  ],
);

【讨论】:

以上是关于带有分隔符的颤振组列表视图的主要内容,如果未能解决你的问题,请参考以下文章

在颤动中创建一个带有分隔符的开关列表图块

如何在listview中使用jquery动态显示列表分隔符?

如何将多个字符串列表与分隔符结合起来

带有列表视图和列的颤振布局

带有过滤条件项的列表视图构建器分页(颤振)

如何在微调器项目之间显示分隔符?