基础列表
显示数据列表是移动应用程序的基本模式。 Flutter包含ListView部件,使列表变得轻而易举!
创建一个ListView
使用标准的ListView构造函数非常适合仅包含少量项目的列表。 我们还将使用内置的ListTile部件来为我们的项目提供一个可视结构。
代码语言:javascript复制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'),
),
],
);
完整例子
代码语言:javascript复制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,这将覆盖默认的垂直方向。
代码语言:javascript复制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,
),
],
)
完整例子
代码语言:javascript复制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构造函数。
虽然默认的ListView构造函数要求我们一次创建所有条目,但ListView.builder构造函数将在滚动到屏幕上时创建条目。
1.创建一个数据源
首先,我们需要一个数据源来处理。 例如,您的数据源可能是消息列表,搜索结果或商店中的产品。 大多数情况下,这些数据将来自互联网或数据库。
在这个例子中,我们将使用List.generate构造函数生成一个10000个字符串的列表。
代码语言:javascript复制final items = new List<String>.generate(10000, (i) => "Item $i");
2.将数据源转换成部件
为了显示我们的字符串列表,我们需要将每个字符串呈现为一个部件!
这是ListView.builder将发挥作用的地方。 在我们的例子中,我们将在它自己的行上显示每个字符串。
代码语言:javascript复制new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return new ListTile(
title: new Text('${items[index]}'),
);
},
);
完整例子
代码语言:javascript复制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创建这样一个结构?
路线
- 使用不同类型的条目创建数据源
- 将数据源转换为部件列表
1.使用不同类型的条目创建数据源
项目类型
为了在列表中表示不同类型的项目,我们需要为每种类型的项目定义一个类别。
在这个例子中,我们将在一个应用程序上显示一个标题,后面跟着五条消息。 因此,我们将创建三个类:ListItem,HeadingItem和MessageItem。
代码语言:javascript复制// 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);
}
创建项目列表 大多数情况下,我们会从互联网或本地数据库获取数据,并将这些数据转换为项目列表。
对于这个例子,我们将生成一个项目列表来处理。 该列表将包含一个标题,后跟五个消息。 冲洗,重复。
代码语言:javascript复制final items = new List<ListItem>.generate(
1200,
(i) => i % 6 == 0
? new HeadingItem("Heading $i")
: new MessageItem("Sender $i", "Message body $i"),
);
2.将数据源转换为部件列表
为了处理将每个项目转换为部件,我们将使用ListView.builder构造函数。
一般来说,我们希望提供一个builder函数来检查我们正在处理的项目类型,并返回该类型项目的相应部件。
在这个例子中,使用is关键字来检查我们正在处理的项目类型可能非常方便。 速度很快,并会自动将每个项目转换为适当的类型。 但是,如果您更喜欢另一种模式,则有不同的方法可以解决此问题!
代码语言:javascript复制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),
);
}
},
);
完整例子
代码语言:javascript复制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的工作原理。
代码语言:javascript复制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,
),
);
}),
);
完整例子
代码语言:javascript复制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,
),
);
}),
),
),
);
}
}