我们经常需要创建显示不同类型内容的列表。例如,我们可能正在制作一个列表,其中显示一个标题,后面跟着与该标题相关的几个子项,再后面是另一个标题,等等。
我们如何用Flutter创建这样的结构?
步骤
- 使用不同类型的数据创建数据源
- 将数据源转换为Widgets列表
1. 使用不同类型的数据创建数据源
条目(子项)类型
为了表示列表中的不同类型的条目,我们需要为每个类型的条目定义一个类。
在这个例子中,我们将在一个应用程序上显示一个标题,后面跟着五条消息。因此,我们将创建三个类:ListItem、HeadingItem、和MessageItem。
// The base class for the different types of items the List can containabstract class ListItem {}// A ListItem that contains data to display a headingclass HeadingItem implements ListItem {final String heading;HeadingItem(this.heading);}// A ListItem that contains data to display a messageclass MessageItem implements ListItem {final String sender;final String body;MessageItem(this.sender, this.body);}
创建Item列表
大多数时候,我们会从互联网或本地数据库中读取数据,并将该数据转换成item的列表。
对于这个例子,我们将生成一个Item列表来处理。该列表将包含一个标题、后跟五条消息,然后重复。
final items = new List<ListItem>.generate(1200,(i) => i % 6 == 0? new HeadingItem("Heading $i"): new MessageItem("Sender $i", "Message body $i"),);
2. 将数据源转换为Widgets列表
为了将每个item转换为Widget,我们将使用ListView.builder构造函数。
通常,我们需要提供一个builder函数来检查我们正在处理的item类型,并返回该item类型对应的Widget。
在这个例子中,使用is关键字来检查我们正在处理的item的类型,这个速度很快,并会自动将每个item转换为适当的类型。
但是,如果您更喜欢另一种模式,也有不同的方法可以解决这个问题!
new ListView.builder(// Let the ListView know how many items it needs to builditemCount: items.length,// Provide a builder function. This is where the magic happens! We'll// convert each item into a Widget based on the type of item it is.itemBuilder: (context, index) {final item = items[index];if (item is HeadingItem) {return new ListTile(title: new Text(item.heading,style: Theme.of(context).textTheme.headline,),);} else if (item is MessageItem) {return new ListTile(title: new Text(item.sender),subtitle: new Text(item.body),);}},);
完整的例子
import 'package:flutter/foundation.dart';import 'package:flutter/material.dart';void main() {runApp(new MyApp(items: new List<ListItem>.generate(1000,(i) => i % 6 == 0? new HeadingItem("Heading $i"): new MessageItem("Sender $i", "Message body $i"),),));}class MyApp extends StatelessWidget {final List<ListItem> items;MyApp({Key key, @required this.items}) : super(key: key);@overrideWidget build(BuildContext context) {final title = 'Mixed List';return new MaterialApp(title: title,home: new Scaffold(appBar: new AppBar(title: new Text(title),),body: new ListView.builder(// Let the ListView know how many items it needs to builditemCount: items.length,// Provide a builder function. This is where the magic happens! We'll// convert each item into a Widget based on the type of item it is.itemBuilder: (context, index) {final item = items[index];if (item is HeadingItem) {return new ListTile(title: new Text(item.heading,style: Theme.of(context).textTheme.headline,),);} else if (item is MessageItem) {return new ListTile(title: new Text(item.sender),subtitle: new Text(item.body),);}},),),);}}// The base class for the different types of items the List can containabstract class ListItem {}// A ListItem that contains data to display a headingclass HeadingItem implements ListItem {final String heading;HeadingItem(this.heading);}// A ListItem that contains data to display a messageclass MessageItem implements ListItem {final String sender;final String body;MessageItem(this.sender, this.body);}
