Flutter使用文档
创建应用主题
为了在整个应用程序中共享包含颜色和字体样式的主题,我们可以提供ThemeData给MaterialApp的构造函数。
如果没有提供theme,Flutter将创建一个默认主题。
new MaterialApp(
title: title,
theme: new ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.lightBlue[800],
accentColor: Colors.cyan[600],
),
);
显示图片
显示图片是大多数移动应用程序的基础。Flutter提供了Image Widget来显示不同类型的图片。
//支持GIF动画
new Image.network(
'https://raw.githubusercontent.com/flutter/website/master/_includes/code/layout/lakes/images/lake.jpg',
)
FadeInImage适用于任何类型的图片:内存、本地Asset或来自网上的图片。
new FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: 'https://github.com/flutter/website/blob/master/_includes/code/layout/lakes/images/lake.jpg?raw=true',
);
缓存图片,在从网上下载图片后缓存图片可能会很方便,以便它们可以脱机使用。
new CachedNetworkImage(
placeholder: new CircularProgressIndicator(),
imageUrl: 'https://github.com/flutter/website/blob/master/_includes/code/layout/lakes/images/lake.jpg?raw=true',
);
可以看到使用CachedNetworkImage同时也可以使用占位符,可以使用任何的Widget作为占位符!
ListView(短列表)
new ListView(
children: [
new ListTile(
leading: new Icon(Icons.map),
title: new Text('Maps'),
),
new ListTile(
leading: new Icon(Icons.photo_album),
title: new Text('Album'),
),
new ListTile(
leading: new Icon(Icons.phone),
title: new Text('Phone'),
),
],
);
水平的ListView
new ListView(
// This next line does the trick.
scrollDirection: Axis.horizontal,
children: [
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,
),
],
)
只需要指定scrollDirection: Axis.horizontal即可,默认当然是垂直的。
ListView.builder(长列表)
处理包含大量数据的列表,最好使用ListView.builder构造函数。ListView的构造函数需要一次创建所有项目,但ListView.builder的构造函数不需要,它将在列表项滚动到屏幕上时创建该列表项。
- 创建一个数据源
final items = new List
.generate(10000, (i) => "Item $i"); - 将数据源转化为Widgets
new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
return new ListTile(
title: new Text('${items[index]}'),
);
},
);
创建不同item的ListView.builder
大多数情况下,List Item并不是完全相同的。当然Flutter也可以创建不同Item的ListView
- 首先创建不同的Item类型
// 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);
}
- 创建Item列表
inal items = new List.generate(
1200,
(i) => i % 6 == 0
? new HeadingItem("Heading $i")
: new MessageItem("Sender $i", "Message body $i"),
);
- 将数据源转换为Widgets列表
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),
);
}
},
);
点击事件
在Flutter中GestureDetector Widget这个也属于一个widget,手势操作在Android中属于一个事件。
创建一个自定义按钮,当点击时显示一个SnackBar。
// Our GestureDetector wraps our button
new GestureDetector(
// When the child is tapped, show a snackbar
onTap: () {
final snackBar = new SnackBar(content: new Text("Tap"));
Scaffold.of(context).showSnackBar(snackBar);
},
// Our Custom Button!
child: new Container(
padding: new EdgeInsets.all(12.0),
decoration: new BoxDecoration(
color: Theme.of(context).buttonColor,
borderRadius: new BorderRadius.circular(8.0),
),
child: new Text('My Button'),
),
);
滑动手势
滑动手势也是一个Widget。
- 创建数据源
final items = new List.generate(20, (i) => "Item ${i + 1}");
- Dismissible Widget(滑动item)
new Dismissible(
// Each Dismissible must contain a Key. Keys allow Flutter to
// uniquely identify Widgets.
key: new Key(item),
// We also need to provide a function that will tell our app
// what to do after an item has been swiped away.
onDismissed: (direction) {
// Remove the item from our data source
items.removeAt(index);
// Show a snackbar! This snackbar could also contain "Undo" actions.
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("$item dismissed")));
},
child: new ListTile(title: new Text('$item')),
);
- ListView.builder创建item
new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return new Dismissible(
// Each Dismissible must contain a Key. Keys allow Flutter to
// uniquely identify Widgets.
key: new Key(item),
// We also need to provide a function that will tell our app
// what to do after an item has been swiped away.
onDismissed: (direction) {
items.removeAt(index);
Scaffold.of(context).showSnackBar(
new SnackBar(content: new Text("$item dismissed")));
},
// Show a red background as the item is swiped away
background: new Container(color: Colors.red),
child: new ListTile(title: new Text('$item')),
);
Navigator
创建两个页面
class FirstScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('First Screen'),
),
body: new Center(
child: new RaisedButton(
child: new Text('Launch new screen'),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new SecondScreen()),
);
},
),
),
);
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text("Second Screen"),
),
body: new Center(
child: new RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: new Text('Go back!'),
),
),
);
}
}
点击跳转到下一个页面
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(builder: (context) => new SecondScreen()),
);
}
调用Navigator.pop返回第一个页面
onPressed: () {
Navigator.pop(context);
}
Widget传值
- 创建model
class Todo {
final String title;
final String description;
Todo(this.title, this.description);
}
- 创建一个model List集合
final todos = new List.generate(
20,
(i) => new Todo(
'Todo $i',
'A description of what needs to be done for Todo $i',
),
);
- 用一个ListView.builder将点击对应item的数据传到详情界面
new ListView.builder(
itemCount: todos.length,
itemBuilder: (context, index) {
return new ListTile(
title: new Text(todos[index].title),
// When a user taps on the ListTile, navigate to the DetailScreen.
// Notice that we're not only creating a new DetailScreen, we're
// also passing the current todo to it!
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new DetailScreen(todo: todos[index]),
),
);
},
);
},
);
- 在Detail页面接收数据
class DetailScreen extends StatelessWidget {
// Declare a field that holds the Todo
final Todo todo;
// In the constructor, require a Todo
DetailScreen({Key key, @required this.todo}) : super(key: key);
@override
Widget build(BuildContext context) {
// Use the Todo to create our UI
return new Scaffold(
appBar: new AppBar(
title: new Text("${todo.title}"),
),
body: new Padding(
padding: new EdgeInsets.all(16.0),
child: new Text('${todo.description}'),
),
);
}
}