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: <Widget>[
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: <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,
),
],
)
只需要指定scrollDirection: Axis.horizontal即可,默認當然是垂直的。
ListView.builder(長列表)
處理包含大量數據的列表,最好使用ListView.builder構造函數。ListView的構造函數需要一次創建所有項目,但ListView.builder的構造函數不需要,它將在列表項滾動到屏幕上時創建該列表項。
- 創建一個數據源
final items = new List<String>.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<ListItem>.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<String>.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<Todo>.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}'),
),
);
}
}