Je cherche des conseils pour créer des listes de vues avec des séparateurs. Par exemple, je voudrais prendre les messages d'une base de données groupée par date et séparer les messages par date avec un graphique ou une ligne, etc., puis placer les messages sous le séparateur. Il serait souhaitable d’essayer cela dans le flutter et tout guidage ou Pousser dans la bonne direction.
Je m'excuse pour la laideur du design, mais juste pour vous montrer que vous pouvez très bien construire votre propre design que vous désirez, voici un exemple rapide:
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: () {})
],
)
],
),
);
}
}
Pour une meilleure conception, vous pouvez supprimer les bordures et utiliser plutôt une 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,),
],
)
],
),
Et une meilleure solution visuelle à mon avis est d’utiliser une Card
au lieu de 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,),
],
)
],
),
);
mettez simplement la ListItem
dans une Container
et ajoutez une décoration:
@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()
)
)
);
}
Bien que cela ne soit pas applicable à votre situation, un moyen simple d’ajouter des séparateurs à un ListView consiste à utiliser 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;
}
}
MODIFIER:
ListTile.divideTiles n'est pas le bon choix pour les listes construites de manière dynamique. L'ajout d'un diviseur au stade où l'élément de liste est créé est probablement la meilleure voie à suivre:
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')));
}
}
Une solution beaucoup plus propre et simple consisterait à utiliser les méthodes suivantes
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")),
),
)
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);
Le code productListAdapter est ici
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),
),
);
}
}