Flutter 手势 - 跟随手指运动的小球
设置小球坐标变量 : 其中 currentX 是距离左侧边界的距离 , currentY 是距离右侧边界的距离 ;
1 2 3 4 |
/// 当前小球的 x 坐标 double currentX = 0; /// 当前小球的 y 坐标 double currentY = 0; |
小球的位置 : 小球是在 Stack 帧布局中的 Positioned 组件 , 其 left 和 top 字段值设置其坐标 , 分别对应 currentX 和 currentY 值 ;
1 2 3 4 5 6 |
// 小球 Positioned( /// 当前位置 left: currentX, top: currentY, ) |
监听事件 : 监听 GestureDetector 组件的 onPanUpdate 事件 , 其回调方法是 void Function(DragUpdateDetails details) 类型的 方法 , 可以从 DragUpdateDetails 类型参数中获取当前 x , y 的移动距离 , 该距离需要与之前的距离累加 , 才能得到准确的坐标值 ;
在回调方法中调用 setState 方法 , 修改成员变量 currentX 和 currentY , 从而修改 Positioned 组件的位置 , 以达到小球移动的目的 ;
1 2 3 4 5 6 7 8 9 10 11 |
/// 手势检测组件 child: GestureDetector( /// 移动操作 onPanUpdate: (e){ setState(() { // e 中只能获取到 delta 值 , 需要逐步累加 currentX += e.delta.dx; currentY += e.delta.dy; }); }, ) |
代码示例 :
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 |
// 小球 Positioned( /// 当前位置 left: currentX, top: currentY, /// 手势检测组件 child: GestureDetector( /// 移动操作 onPanUpdate: (e){ setState(() { // e 中只能获取到 delta 值 , 需要逐步累加 currentX += e.delta.dx; currentY += e.delta.dy; }); }, // 黑色小球 child: Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(20), ), ), ),), |
完整代码示例
完整代码示例 :
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 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; class GesturePage extends StatefulWidget { const GesturePage({Key? key}) : super(key: key); @override _GesturePageState createState() => _GesturePageState(); } class _GesturePageState extends State<GesturePage> { /// 当前小球的 x 坐标 double currentX = 0; /// 当前小球的 y 坐标 double currentY = 0; @override Widget build(BuildContext context) { return MaterialApp( // 设置主题 theme: ThemeData( primarySwatch: Colors.amber, ), // 设置主体组件 home: Scaffold( // 设置标题栏 appBar: AppBar( title: const Text("手势检测"), // 返回按钮设置 leading: GestureDetector( // 点击事件回调函数 onTap: () { // 退出当前界面 Navigator.pop(context); }, // 回退按钮图标 child: const Icon(Icons.arrow_back), ), ), // 水平/垂直方向平铺组件 body: FractionallySizedBox( // 水平方向平铺 widthFactor: 1, // 帧布局 child: Stack( children: <Widget>[ // 垂直方向线性布局 Column( children: <Widget>[ // 手势检测组件 GestureDetector( // 点击事件 onTap: () { if (kDebugMode) { print("双击"); } }, // 双击事件 onDoubleTap: () { if (kDebugMode) { print("双击"); } }, // 长按事件 , ()=>方法名(参数列表) 即可回调一个现有方法 onLongPress: () => _longPress(), // 点击取消 onTapCancel: () { if (kDebugMode) { print("点击取消"); } }, // 点击按下 onTapDown: (e) { if (kDebugMode) { print("点击按下"); } }, // 点击抬起 onTapUp: (e) { if (kDebugMode) { print("点击抬起"); } }, // 手势检测的作用组件 , 监听该组件上的各种手势 child: Container( // 子组件居中 alignment: Alignment.center, // 内边距 padding: const EdgeInsets.all(100), // 背景装饰 decoration: const BoxDecoration( color: Colors.green, ), child: const Text( "手势检测", style: TextStyle( fontSize: 50, color: Colors.red, ), ), ), ) ], ), // 小球 Positioned( /// 当前位置 left: currentX, top: currentY, /// 手势检测组件 child: GestureDetector( /// 移动操作 onPanUpdate: (e) { setState(() { // e 中只能获取到 delta 值 , 需要逐步累加 currentX += e.delta.dx; currentY += e.delta.dy; }); }, // 黑色小球 child: Container( width: 40, height: 40, decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.circular(20), ), ), ), ), ], ), ), ), ); } /// 长按事件 void _longPress() { if (kDebugMode) { print("长按"); } } } |
运行效果 :