logo头像
Snippet 博客主题

Flutter widgets

本文于325天之前发表,文中内容可能已经过时。

Flutter widgets

- 有些widgets是有状态的, 有些是无状态的
- 如果用户与widget交互,widget会发生变化,那么它就是有状态的.
- widget的状态(state)是一些可以更改的值, 如一个slider滑动条的当前值或checkbox是否被选中.
- widget的状态保存在一个State对象中, 它和widget的布局显示分离。
- 当widget状态改变时, State 对象调用setState(), 告诉框架去重绘widget.

stateless widget 没有内部状态. Icon、 IconButton, 和Text 都是无状态widget, 他们都是 StatelessWidget的子类。

stateful widget 是动态的. 用户可以和其交互 (例如输入一个表单、 或者移动一个slider滑块),或者可以随时间改变 (也许是数据改变导致的UI更新). Checkbox, Radio, Slider, InkWell, Form, and TextField 都是 stateful widgets, 他们都是 StatefulWidget的子类。

创建一个有状态的widget

- 要创建一个自定义有状态widget,需创建两个类:StatefulWidget和State
- 状态对象包含widget的状态和build() 方法。
- 当widget的状态改变时,状态对象调用setState(),告诉框架重绘widget

实现一个自定义的有状态widget需要创建两个类:

定义一个widget类,继承自StatefulWidget.
包含该widget状态并定义该widget build()方法的类,它继承自State.

Step 1: 决定哪个对象管理widget的状态

Widget的状态可以通过多种方式进行管理,但在我们的示例中,widget本身(FavoriteWidget)将管理自己的状态。 在这个例子中,切换星形图标是一个独立的操作,不会影响父窗口widget或其他用户界面,因此该widget可以在内部处理它自己的状态。

在管理状态中了解更多关于widget和状态的分离以及如何管理状态的信息。

Step 2: 创建StatefulWidget子类

FavoriteWidget类管理自己的状态,因此它重写createState()来创建状态对象。 框架会在构建widget时调用createState()。在这个例子中,createState()创建_FavoriteWidgetState的实例,您将在下一步中实现该实例。

1
2
3
4
class FavoriteWidget extends StatefulWidget {
@override
_FavoriteWidgetState createState() => new _FavoriteWidgetState();
}

注意:

以下划线(_)开头的成员或类是私有的。有关更多信息,请参阅Dart语言参考中的库和可见性部分 。

Step 3: 创建State子类

自定义State类存储可变信息 - 可以在widget的生命周期内改变逻辑和内部状态。 当应用第一次启动时,用户界面显示一个红色实心的星星形图标,表明该湖已经被收藏,并有41个“喜欢”。状态对象存储这些信息在_isFavorited和_favoriteCount变量。

状态对象也定义了build方法。此build方法创建一个包含红色IconButton和Text的行。 该widget使用IconButton(而不是Icon), 因为它具有一个onPressed属性,该属性定义了处理点击的回调方法。IconButton也有一个icon的属性,持有Icon。

按下IconButton时会调用_toggleFavorite()方法,然后它会调用setState()。 调用setState()是至关重要的,因为这告诉框架,widget的状态已经改变,应该重绘。 _toggleFavorite在: 1)实心的星形图标和数字“41” 和 2)虚心的星形图标和数字“40”之间切换UI。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class _FavoriteWidgetState extends State<FavoriteWidget> {
bool _isFavorited = true;
int _favoriteCount = 41;

void _toggleFavorite() {
setState(() {
// If the lake is currently favorited, unfavorite it.
if (_isFavorited) {
_favoriteCount -= 1;
_isFavorited = false;
// Otherwise, favorite it.
} else {
_favoriteCount += 1;
_isFavorited = true;
}
});
}

@override
Widget build(BuildContext context) {
return new Row(
mainAxisSize: MainAxisSize.min,
children: [
new Container(
padding: new EdgeInsets.all(0.0),
child: new IconButton(
icon: (_isFavorited
? new Icon(Icons.star)
: new Icon(Icons.star_border)),
color: Colors.red[500],
onPressed: _toggleFavorite,
),
),
new SizedBox(
width: 18.0,
child: new Container(
child: new Text('$_favoriteCount'),
),
),
],
);
}
}

案例二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import 'package:flutter/material.dart';
void main() {
runApp(
new MaterialApp(
title: 'Flutter实例',
home: new Counter(),
),
);
}
class CounterDisplay extends StatelessWidget {
CounterDisplay({this.count});
final int count;
@override
Widget build(BuildContext context) {
return new Center(
child: new Text('按钮点击 $count 次'),
);
}
}
class CounterIncrementor extends StatelessWidget {
CounterIncrementor({this.onPressed});
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return new FloatingActionButton(
onPressed: onPressed,
tooltip: '增加',
child: new Icon(Icons.add),
);
}
}
class Counter extends StatefulWidget {
@override
_CounterState createState() => new _CounterState();
}
class _CounterState extends State<Counter> {
int _count = 0;
void _increment() {
setState(
() {
_count += 1;
}
);
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Flutter实例'),
),
body: new CounterDisplay(count: _count),
floatingActionButton: new CounterIncrementor(onPressed: _increment),
);
}
}

案例二 中 不同空间中状态

floatingActionButton 点击 点击次数增加
CounterDisplay 中显示 点击 数量

所有 Counter 管理状态

支付宝打赏 微信打赏

打赏