Flutter 手势 - 跟随手指运动的小球
设置小球坐标变量 : 其中 currentX 是距离左侧边界的距离 , currentY 是距离右侧边界的距离 ;
/// 当前小球的 x 坐标 double currentX = 0; /// 当前小球的 y 坐标 double currentY = 0;
小球的位置 : 小球是在 Stack 帧布局中的 Positioned 组件 , 其 left 和 top 字段值设置其坐标 , 分别对应 currentX 和 currentY 值 ;
// 小球 Positioned( /// 当前位置 left: currentX, top: currentY, )
监听事件 : 监听 GestureDetector 组件的 onPanUpdate 事件 , 其回调方法是 void Function(DragUpdateDetails details) 类型的 方法 , 可以从 DragUpdateDetails 类型参数中获取当前 x , y 的移动距离 , 该距离需要与之前的距离累加 , 才能得到准确的坐标值 ;
在回调方法中调用 setState 方法 , 修改成员变量 currentX 和 currentY , 从而修改 Positioned 组件的位置 , 以达到小球移动的目的 ;
/// 手势检测组件 child: GestureDetector( /// 移动操作 onPanUpdate: (e){ setState(() { // e 中只能获取到 delta 值 , 需要逐步累加 currentX += e.delta.dx; currentY += e.delta.dy; }); }, )
代码示例 :
// 小球 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), ), ), ),),
完整代码示例
完整代码示例 :
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("长按"); } } }
运行效果 :