我怎么給 Flutter 的 widget 添加一個點擊監聽者?
在 iOS 中,你給一個 view 添加 GestureRecognizer 來處理點擊事件。在 Flutter 中,有兩種方法來添加點擊監聽者:
-
如果 widget 本身支持事件監測,直接傳遞給它一個函數,並在這個函數里實現響應方法。例如,
RaisedButtonwidget 擁有一個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(); } }
