ViewControllers
在 Flutter 中,使用Widgets代替ViewControllers来管理用户界面。使用 Navigator 在 Route 之间跳转,或者渲染相同数据的不同状态。
可以通过hook WidgetsBinding
观察者来监听生命周期事件。并监听didChangeAppLifecycleState()
的变化事件。
可观察的生命周期事件有:
- inactive — 应用处于不活跃的状态,并且不会接受用户的输入。(仅用于iOS,安卓端没有等价事件);
- paused - 应用暂时对用户不可见,虽然不接受用户输入,但是是在后台运行的;
- resumed - 应用可见,也响应用户的输入;
- suspending - 应用暂时被挂起,在iOS上没有这一事件。
这些状态的更多细节和含义,可以查看AppLifecycleStatus documentation;
手势与触摸事件
在Flutter中有两种方法来添加点击监听者:
- 如果widget本身支持事件监测,直接传递给它一个函数,并在这个函数里实现响应方法。例如:RaisedButton Widget拥有一个RaisedButton参数:
1
2
3
4
5
6
7
8
9
@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: () {
print("click");
},
child: Text("Button"),
);
}
- 如果本身不支持事件监测,则在外面包裹一个GestureDetector,并给他的onTap属性传递一个函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class GestureSampleAppGesturePage extends StatelessWidget {
const GestureSampleAppGesturePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('手势与触摸事件'),
),
body: Center(
child: GestureDetector(
child: FlutterLogo(
size: 200.0,
),
onTap: () {
print("tap");
},
),
)
);
}
}
处理其他手势
使用GestureDetector还可以监听其他手势,比如:
- Tapping
- onTapDown — 在特定位置轻触手势接触了屏幕。
- onTapUp — 在特定位置产生了一个轻触手势,并停止接触屏幕。
- onTap — 产生了一个轻触手势。
- onTapCancel — 触发了 onTapDown 但没能触发 tap。
- Double tapping
- onDoubleTap — 用户在同一个位置快速点击了两下屏幕。
- Long pressing
- onLongPress — 用户在同一个位置长时间接触屏幕。
- Vertical dragging
- onVerticalDragStart — 接触了屏幕,并且可能会垂直移动。
- onVerticalDragUpdate — 接触了屏幕,并继续在垂直方向移动。
- onVerticalDragEnd — 之前接触了屏幕并垂直移动,并在停止接触屏幕前以某个垂直的速度移动。
- Horizontal dragging
- onHorizontalDragStart — 接触了屏幕,并且可能会水平移动。
- onHorizontalDragUpdate — 接触了屏幕,并继续在水平方向移动。
- onHorizontalDragEnd — 之前接触屏幕并水平移动的触摸点与屏幕分离。
双击手势示例:
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class GestureSampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Text',
theme: ThemeData(
primaryColor: Colors.blue
),
// home: GestureSampleAppGesturePage(),
// home: GestureSampleAppButtonPage(),
home: DoubleTapAnimation(),
);
}
}
// 本身包含事件监测
class GestureSampleAppButtonPage extends StatelessWidget {
const GestureSampleAppButtonPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('手势与触摸事件'),
),
body: Center(
child: RaisedButton(
onPressed: (){
print('click');
},
child: Text('Button'),
color: Colors.red,
),
)
);
}
}
// 不包含事件监测
class GestureSampleAppGesturePage extends StatelessWidget {
const GestureSampleAppGesturePage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('手势与触摸事件'),
),
body: Center(
child: GestureDetector(
child: FlutterLogo(
size: 200.0,
),
onTap: () {
print("tap");
},
),
)
);
}
}
// 双击旋转图标,结合动画
class DoubleTapAnimation extends StatefulWidget {
DoubleTapAnimation({Key key}) : super(key: key);
_DoubleTapAnimationState createState() => _DoubleTapAnimationState();
}
class _DoubleTapAnimationState extends State<DoubleTapAnimation> with TickerProviderStateMixin {
AnimationController controller;
CurvedAnimation curve;
@override
void initState() {
controller = AnimationController(duration: const Duration(milliseconds: 1000), vsync: this);
curve = CurvedAnimation(parent: controller, curve: Curves.easeIn);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Double Tap'),
),
body: Center(
child: GestureDetector(
child: RotationTransition(
child: FlutterLogo(
size: 200,
),
turns: curve,
),
onDoubleTap: () {
if (controller.isCompleted) {
controller.reverse();
} else {
controller.forward();
}
print('double tap');
},
),
),
);
}
}