顯示數據列表是移動應用程序的基本模式。 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, ), ); }), ), ), ); } }