Flutter - 手势简介
Flutter - 手势简介
Section titled “Flutter - 手势简介”手势是用户与触控应用交互的主要方式。Flutter 提供了一个强大且灵活的系统,用于检测和响应各种用户手势,从简单的轻触到复杂的拖动和缩放。
移动应用用户期望应用能响应各种触控输入,包括:
- 轻触 (Tap): 在屏幕表面短暂触碰。
- 双击 (Double Tap): 在同一位置快速连续触碰两次。
- 长按 (Long Press): 触碰屏幕并按住较长时间。
- 拖动 / 平移 (Drag / Pan): 触碰屏幕并在其上移动手指。
-
- 垂直拖动: 主要的垂直移动。
-
- 水平拖动: 主要的水平移动。
- 缩放 / 双指开合 (Scale / Pinch): 使用两根手指靠近(捏合/缩小)或分开(张开/放大)。
- 滑动 / 抛掷 (Flick / Fling): 快速拖动并释放的动作,通常会导致持续的移动(例如滚动)。
GestureDetector 部件
Section titled “GestureDetector 部件”Flutter 用于手势检测的主要工具是 GestureDetector 部件。它是一个非可视化的部件,这意味着它本身不绘制任何内容。相反,你将需要使其具备交互功能的部件包裹在 GestureDetector 内部。
GestureDetector 监听其子部件上的各种触控事件,并在识别到手势时调用相应的回调函数。
关键的 GestureDetector 回调
Section titled “关键的 GestureDetector 回调”GestureDetector 为不同的手势提供了许多回调:
-
轻触手势:
-
onTap:轻触手势完成时调用。
-
onTapDown:用户首次触碰屏幕,开始潜在轻触时调用。
-
onTapUp:用户释放屏幕,结束潜在轻触时调用。
-
onTapCancel:如果潜在轻触被取消(例如,手指移动太远)时调用。
-
onDoubleTap:双击时调用。
-
onLongPress:长按时调用。
-
拖动手势(垂直、水平、平移):
-
onVerticalDragStart、onVerticalDragUpdate、onVerticalDragEnd
-
onHorizontalDragStart、onHorizontalDragUpdate、onHorizontalDragEnd
-
onPanStart、onPanUpdate、onPanEnd(适用于任意方向的拖动)
-
- 这些回调提供了
DragUpdateDetails或类似对象,包含关于拖动位置和增量 (delta) 的信息。
- 这些回调提供了
-
缩放手势:
-
onScaleStart、onScaleUpdate、onScaleEnd
-
- 提供
ScaleUpdateDetails,包含scale、rotation、focalPoint等信息。
- 提供
GestureDetector 尝试为每次指针交互仅识别一个手势。当多个检测器可能从同一输入事件中识别出手势时(例如,决定是轻触还是垂直拖动),它会使用手势竞技场 (gesture arena) 来消除歧义。
示例:带对话框的可轻触的 ‘Hello World’
Section titled “示例:带对话框的可轻触的 ‘Hello World’”让我们修改简单的 ‘Hello World’ 应用,使其在文本被轻触时显示一个对话框。
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget { const MyApp({super.key});
@override Widget build(BuildContext context) { return MaterialApp( title: 'Gesture Demo', home: const MyHomePage(title: 'Gesture Demo Home Page'), ); }}
class MyHomePage extends StatelessWidget { const MyHomePage({super.key, required this.title}); final String title;
// 显示对话框的函数 void _showDialog(BuildContext context) { showDialog( context: context, builder: (BuildContext context) { // 返回 Dialog 类型对象 return AlertDialog( title: const Text("Message"), content: const Text("Hello World Tapped!"), actions: <Widget>[ TextButton( // 使用 TextButton 代替已弃用的 FlatButton child: const Text("Close"), onPressed: () { Navigator.of(context).pop(); // 关闭对话框 }, ), ], ); },\n ); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(title)), body: Center( // 使用 GestureDetector 包裹 Text 部件 child: GestureDetector( onTap: () { // 轻触时调用显示对话框的函数 _showDialog(context); }, child: const Text( 'Hello World', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), ), ), ); }}在此示例中,Text 部件被 GestureDetector 包裹。onTap 回调被实现为调用 _showDialog,该函数使用内置的 showDialog 函数和 AlertDialog 部件来显示一个简单的弹出框。
其他与手势相关的部件
Section titled “其他与手势相关的部件”Flutter 提供了其他专门用于交互的部件:
Listener: 一个较低层级的部件,报告原始指针事件(PointerDownEvent、PointerMoveEvent、PointerUpEvent、PointerCancelEvent)。对于自定义手势识别或跟踪指针移动很有用。InkWell和InkResponse: Material Design 部件,在轻触时显示视觉上的水波纹效果。常用于使非按钮部件可轻触并提供视觉反馈。Dismissible: 允许通过滑动(抛掷)部件(通常是列表项)来将其移除。Draggable和LongPressDraggable: 使部件可拖动。DragTarget: 一个可以接受被拖放到其上的Draggable部件。IgnorePointer和AbsorbPointer: 控制部件及其子树是否参与命中测试(手势检测)。IgnorePointer对命中测试不可见,而AbsorbPointer会消耗命中事件但阻止下层部件接收它。Scrollable和可滚动视图部件(ListView、GridView、SingleChildScrollView): 自动处理滚动手势。
选择正确的部件取决于你想要实现的具体交互。GestureDetector 是通用工具,而 InkWell 或 Dismissible 等其他部件则提供更具体的行为和视觉效果。