我怎么给 Flutter 的 widget 添加一个点击监听者?
在 iOS 中,你给一个 view 添加 GestureRecognizer
来处理点击事件。在 Flutter 中,有两种方法来添加点击监听者:
-
如果 widget 本身支持事件监测,直接传递给它一个函数,并在这个函数里实现响应方法。例如,
RaisedButton
widget 拥有一个RaisedButton
参数:@override Widget build(BuildContext context) { return RaisedButton( onPressed: () { print("click"); }, child: Text("Button"), ); }
- 如果 widget 本身不支持事件监测,则在外面包裹一个 GestureDetector,并给它的 onTap 属性传递一个函数:
class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( body: Center( child: GestureDetector( child: FlutterLogo( size: 200.0, ), onTap: () { print("tap"); }, ), ), ); } }
我怎么处理 widget 上的其他手势?
使用
GestureDetector
你可以监听更广阔范围内的手势,比如:- Tapping
onTapDown
— 在特定位置轻触手势接触了屏幕。onTapUp
— 在特定位置产生了一个轻触手势,并停止接触屏幕。onTap
— 产生了一个轻触手势。onTapCancel
— 触发了onTapDown
但没能触发 tap。
- Double tapping
onDoubleTap
— 用户在同一个位置快速点击了两下屏幕。
- Long pressing
onLongPress
— 用户在同一个位置长时间接触屏幕。
- Vertical dragging
onVerticalDragStart
— 接触了屏幕,并且可能会垂直移动。onVerticalDragUpdate
— 接触了屏幕,并继续在垂直方向移动。onVerticalDragEnd
— 之前接触了屏幕并垂直移动,并在停止接触屏幕前以某个垂直的速度移动。
- Horizontal dragging
onHorizontalDragStart
— 接触了屏幕,并且可能会水平移动。onHorizontalDragUpdate
— 接触了屏幕,并继续在水平方向移动。onHorizontalDragEnd
— 之前接触屏幕并水平移动的触摸点与屏幕分离。
下面这个例子展示了一个
GestureDetector
是如何在双击时旋转 Flutter 的 logo 的: - Tapping
-
import 'package:flutter/material.dart'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: AnimateApp(), ); } } class AnimateApp extends StatefulWidget { @override State<StatefulWidget> createState() { return _AnimateAppState(); } } class _AnimateAppState extends State<AnimateApp> with SingleTickerProviderStateMixin { AnimationController controller; Animation<double> animation; CurvedAnimation curve; @override void initState() { super.initState(); // 创建 AnimationController 对象 controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 2000)); curve = CurvedAnimation(parent: controller, curve: Curves.easeIn); // 通过 Tween 对象 创建 Animation 对象 animation = Tween(begin: 50.0, end: 200.0).animate(controller) ..addListener(() { // 注意:这句不能少,否则 widget 不会重绘,也就看不到动画效果 setState(() {}); }); // 执行动画 controller.forward(); } @override Widget build(BuildContext context) { return MaterialApp( title: 'AnimateApp', theme: ThemeData(primaryColor: Colors.blue), home: Scaffold( appBar: AppBar( title: Text('AnimateApp'), ), body: Center( child: GestureDetector( child: RotationTransition( turns: curve, child: FlutterLogo( size: 200.0, )), onDoubleTap: () { if (controller.isCompleted) { controller.reverse(); } else { controller.forward(); } }, ), ))); } @override void dispose() { // 资源释放 controller.dispose(); super.dispose(); } }