Список флаттер-групп с разделителем

125
9

Я ищу некоторые рекомендации по созданию списков с разделителями. Например, я хотел бы получать сообщения из базы данных, сгруппированной по дате, и отделять сообщения по дате с графикой или строкой и т.д., А затем отправлять сообщения под разделителем. Попытка этого в трепете и любое руководство или толчок в правильном направлении были бы оценены.

спросил(а) 2017-11-11T03:49:00+03:00 2 года, 10 месяцев назад
1
Решение
148

Я прошу прощения за уродство дизайна, но, чтобы показать вам, вы можете в значительной степени создать свой собственный дизайн, который вам нужен, это быстрый пример:

enter image description here

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

ответил(а) 2017-11-11T13:21:00+03:00 2 года, 10 месяцев назад
149

просто поместите 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()
)
)
);
}

ответил(а) 2018-03-01T02:03:00+03:00 2 года, 6 месяцев назад
105

Гораздо чище и проще было бы использовать следующее

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

ответил(а) 2019-01-10T13:45:00+03:00 1 год, 8 месяцев назад
81

Хотя это может быть неприменимо к вашей ситуации, простой способ добавить разделители в 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')));
}
}

ответил(а) 2017-11-11T23:08:00+03:00 2 года, 10 месяцев назад
40

Длинный ответ короткий

Просто используйте 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
],
);

}

ответил(а) 2019-04-16T17:31:00+03:00 1 год, 5 месяцев назад
41

Здесь много слишком сложных ответов

Просто используйте divTiles:

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

Или альтернативно используйте разделенный:

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

ответил(а) 2019-03-13T19:26:00+03:00 1 год, 6 месяцев назад
42

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

ответил(а) 2018-11-17T15:23:00+03:00 1 год, 10 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема