显示数据列表是移动应用程序的基本模式。 Flutter包含ListView部件,使列表变得垂手可得!html
使用标准的ListView构造函数很是适合仅包含少许项目的列表。 咱们还将使用内置的ListTile部件来为咱们的项目提供一个可视结构。java
new ListView( children: <Widget>[ new ListTile( leading: new Icon(Icons.map), title: new Text('Map'), ), new ListTile( leading: new Icon(Icons.photo_album), title: new Text('Album'), ), new ListTile( leading: new Icon(Icons.phone), title: new Text('Phone'), ), ], );
import 'package:flutter/material.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final title = 'Basic List'; return new MaterialApp( title: title, home: new Scaffold( appBar: new AppBar( title: new Text(title), ), body: new ListView( children: <Widget>[ new ListTile( leading: new Icon(Icons.map), title: new Text('Map'), ), new ListTile( leading: new Icon(Icons.photo_album), title: new Text('Album'), ), new ListTile( leading: new Icon(Icons.phone), title: new Text('Phone'), ), ], ), ), ); } }
有时,您可能想要建立一个水平滚动而不是垂直滚动的列表。 ListView部件支持开箱即用的水平列表。数据库
咱们将使用标准的ListView构造函数,经过横向scrollDirection,这将覆盖默认的垂直方向。app
new ListView( // This next line does the trick. scrollDirection: Axis.horizontal, children: <Widget>[ new Container( width: 160.0, color: Colors.red, ), new Container( width: 160.0, color: Colors.blue, ), new Container( width: 160.0, color: Colors.green, ), new Container( width: 160.0, color: Colors.yellow, ), new Container( width: 160.0, color: Colors.orange, ), ], )
import 'package:flutter/material.dart'; void main() => runApp(new MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final title = 'Horizontal List'; return new MaterialApp( title: title, home: new Scaffold( appBar: new AppBar( title: new Text(title), ), body: new Container( margin: new EdgeInsets.symmetric(vertical: 20.0), height: 200.0, child: new ListView( scrollDirection: Axis.horizontal, children: <Widget>[ new Container( width: 160.0, color: Colors.red, ), new Container( width: 160.0, color: Colors.blue, ), new Container( width: 160.0, color: Colors.green, ), new Container( width: 160.0, color: Colors.yellow, ), new Container( width: 160.0, color: Colors.orange, ), ], ), ), ), ); } }
标准的ListView构造函数适用于小列表。 为了处理包含大量项目的列表,最好使用ListView.builder构造函数。less
虽然默认的ListView构造函数要求咱们一次建立全部条目,但ListView.builder构造函数将在滚动到屏幕上时建立条目。ide
首先,咱们须要一个数据源来处理。 例如,您的数据源多是消息列表,搜索结果或商店中的产品。 大多数状况下,这些数据未来自互联网或数据库。函数
在这个例子中,咱们将使用List.generate构造函数生成一个10000个字符串的列表。ui
final items = new List<String>.generate(10000, (i) => "Item $i");
为了显示咱们的字符串列表,咱们须要将每一个字符串呈现为一个部件!this
这是ListView.builder将发挥做用的地方。 在咱们的例子中,咱们将在它本身的行上显示每一个字符串。spa
new ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return new ListTile( title: new Text('${items[index]}'), ); }, );
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; void main() { runApp(new MyApp( items: new List<String>.generate(10000, (i) => "Item $i"), )); } class MyApp extends StatelessWidget { final List<String> items; MyApp({Key key, @required this.items}) : super(key: key); @override Widget build(BuildContext context) { final title = 'Long List'; return new MaterialApp( title: title, home: new Scaffold( appBar: new AppBar( title: new Text(title), ), body: new ListView.builder( itemCount: items.length, itemBuilder: (context, index) { return new ListTile( title: new Text('${items[index]}'), ); }, ), ), ); } }
咱们常常须要建立显示不一样类型内容的列表。 例如,咱们可能正在制做一个列表,其中显示一个标题,后面跟着与该标题相关的几个项目,后面是另外一个标题,等等。
咱们如何用Flutter建立这样一个结构?
路线
项目类型
为了在列表中表示不一样类型的项目,咱们须要为每种类型的项目定义一个类别。
在这个例子中,咱们将在一个应用程序上显示一个标题,后面跟着五条消息。 所以,咱们将建立三个类:ListItem,HeadingItem和MessageItem。
// The base class for the different types of items the List can contain abstract class ListItem {} // A ListItem that contains data to display a heading class HeadingItem implements ListItem { final String heading; HeadingItem(this.heading); } // A ListItem that contains data to display a message class MessageItem implements ListItem { final String sender; final String body; MessageItem(this.sender, this.body); }
建立项目列表
大多数状况下,咱们会从互联网或本地数据库获取数据,并将这些数据转换为项目列表。
对于这个例子,咱们将生成一个项目列表来处理。 该列表将包含一个标题,后跟五个消息。 冲洗,重复。
final items = new List<ListItem>.generate( 1200, (i) => i % 6 == 0 ? new HeadingItem("Heading $i") : new MessageItem("Sender $i", "Message body $i"), );
为了处理将每一个项目转换为部件,咱们将使用ListView.builder构造函数。
通常来讲,咱们但愿提供一个builder函数来检查咱们正在处理的项目类型,并返回该类型项目的相应部件。
在这个例子中,使用is关键字来检查咱们正在处理的项目类型可能很是方便。 速度很快,并会自动将每一个项目转换为适当的类型。 可是,若是您更喜欢另外一种模式,则有不一样的方法能够解决此问题!
new ListView.builder( // Let the ListView know how many items it needs to build itemCount: 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); @override Widget 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 build itemCount: 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 contain abstract class ListItem {} // A ListItem that contains data to display a heading class HeadingItem implements ListItem { final String heading; HeadingItem(this.heading); } // A ListItem that contains data to display a message class MessageItem implements ListItem { final String sender; final String body; MessageItem(this.sender, this.body); }
在某些状况下,您可能但愿将项目显示为网格,而不是显示下一个项目的普通列表。 对于这个任务,咱们将使用GridView部件。
开始使用网格的最简单方法是使用GridView.count构造函数,由于它容许咱们指定咱们想要的行数或列数。
在这个例子中,咱们将生成一个100个部件的列表,在列表中显示它们的索引。 这将帮助咱们可视化GridView的工做原理。
new GridView.count( // Create a grid with 2 columns. If you change the scrollDirection to // horizontal, this would produce 2 rows. crossAxisCount: 2, // Generate 100 Widgets that display their index in the List children: new List.generate(100, (index) { return new Center( child: new Text( 'Item $index', style: Theme.of(context).textTheme.headline, ), ); }), );
import 'package:flutter/material.dart'; void main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { final title = 'Grid List'; return new MaterialApp( title: title, home: new Scaffold( appBar: new AppBar( title: new Text(title), ), body: new GridView.count( // Create a grid with 2 columns. If you change the scrollDirection to // horizontal, this would produce 2 rows. crossAxisCount: 2, // Generate 100 Widgets that display their index in the List children: new List.generate(100, (index) { return new Center( child: new Text( 'Item $index', style: Theme.of(context).textTheme.headline, ), ); }), ), ), ); } }