Flutter实现手势识别功能详解方法
作者:@我不认识你 发布时间:2022-12-21 15:41:41
GestureDetector
GestureDetector 是手势识别的组件,可以识别点击、双击、长按事件、拖动、缩放等手势
点击事件
点击相关事件包括:
onTapDown:按下时回调。
onTapUp:抬起时回调。
onTap:点击事件回调。
onTapCancel:点击取消事件回调。
按下然后抬起调用顺序
onTapDown-> onTapUp-> onTap
按下后移动调用顺序
onTapDown-> onTapCancel
示例
class _YcHomeBodyState extends State<YcHomeBody> {
String desc = '';
Color containerColor = Colors.red;
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Column(
children: [
Container(
width: 420,
height: 330,
color: containerColor,
),
const SizedBox(
width: 100,
height: 20,
),
Text("点击事件:$desc")
],
),
onTapDown: (TapDownDetails tapDownDetails) {
setState(() {
desc += '按下,';
containerColor = Colors.blue;
});
},
onTapUp: (TapUpDetails tapUpDetails) {
setState(() {
desc += '抬起,';
containerColor = Colors.red;
});
},
onTap: () {
setState(() {
desc += '点击,';
containerColor = Colors.yellow;
});
},
onTapCancel: () {
setState(() {
desc += '取消,';
containerColor = Colors.pink;
});
},
);
}
}
双击事件
双击是快速且连续2次在同一个位置点击,双击监听使用onDoubleTap方法
return GestureDetector(
child: Column(
children: [
Container(
width: 420,
height: 330,
color: containerColor,
),
const SizedBox(
width: 100,
height: 20,
),
Text("点击事件:$desc")
],
),
onDoubleTap: () {
setState(() {
desc = '双击了';
});
},
长按事件
长按事件(LongPress)包含长按开始、移动、抬起、结束事件,说明如下:
onLongPressStart:长按开始事件回调。
onLongPressMoveUpdate:长按移动事件回调。
onLongPressUp:长按抬起事件回调。
onLongPressEnd:长按结束事件回调。
onLongPress:长按事件回调。
示例
return GestureDetector(
child: Column(
children: [
Container(
width: 420,
height: 330,
color: containerColor,
),
const SizedBox(
width: 100,
height: 20,
),
Text("点击事件:$desc")
],
),
onLongPressStart: (v) {
setState(() {
desc += '长按开始,';
print("长按开始:$v");
});
},
onLongPressMoveUpdate: (v) {
setState(() {
desc += '长按移动,';
print("长按移动:$v");
});
},
onLongPressUp: () {
setState(() {
desc += '长按抬起,';
print("长按抬起");
});
},
onLongPressEnd: (v) {
setState(() {
desc += '长按结束,';
print("长按结束:$v");
});
},
onLongPress: () {
setState(() {
desc += '长按回调,';
print("长按回调");
});
});
执行顺序
1、长按开始->回调->结束->抬起
2、长按开始->回调->移动->结束->抬起
水平/垂直拖动事件
垂直/水平拖动事件包括按下、开始、移动更新、结束、取消事件,以垂直为例说明如下:
onVerticalDragDown:垂直拖动按下事件回调
onVerticalDragStart:垂直拖动开始事件回调
onVerticalDragUpdate:指针移动更新事件回调
onVerticalDragEnd:垂直拖动结束事件回调
onVerticalDragCancel:垂直拖动取消事件回调
GestureDetector(
onVerticalDragStart: (v) => print('onVerticalDragStart'),
onVerticalDragDown: (v) => print('onVerticalDragDown'),
onVerticalDragUpdate: (v) => print('onVerticalDragUpdate'),
onVerticalDragCancel: () => print('onVerticalDragCancel'),
onVerticalDragEnd: (v) => print('onVerticalDragEnd'),
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
),
)
缩放事件
缩放(Scale)包含缩放开始、更新、结束。说明如下:
onScaleStart:缩放开始事件回调。
onScaleUpdate:缩放更新事件回调。
onScaleEnd:缩放结束事件回调。
GestureDetector(
onScaleStart: (v) => print('onScaleStart'),
onScaleUpdate: (ScaleUpdateDetails v) => print('onScaleUpdate'),
onScaleEnd: (v) => print('onScaleEnd'),
child: Center(
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
),
)
InkWell
InkWell 组件在用户点击时出现“水波纹”效果。事件和属性挺多的,就看一下常用的
设置水波纹颜色
点击和长按都能够触发水波纹,点击波纹效果快,长按波纹效果慢
return InkWell(
onTap: (){
print("点击了");
},
splashColor: Colors.red,
child: const Text('点击InkWell,水波纹'),
);
给字体添加边距和圆角边框,扩大“水波纹”效果:
Center(
child: InkWell(
onTap: () {
print("点击了");
},
splashColor: Colors.red,
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(color: Colors.red),
borderRadius: const BorderRadius.all(Radius.circular(20))),
child: const Text('点击InkWell,水波纹'))),
);
可以看到水波纹会超出圆角,为了解决这个问题可以使用Ink
Ink
Ink控件用于在[Material]控件上绘制图像和其他装饰,以便[InkWell]、[InkResponse]控件的“水波纹”效果在其上面显示。
return Center(
child: Ink(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xFFDE2F21), Color(0xFFEC592F)]),
borderRadius: BorderRadius.all(Radius.circular(20))),
child: InkWell(
borderRadius: const BorderRadius.all(Radius.circular(20)),
child: Container(
padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 20),
child: const Text(
'这是InkWell的点击效果',
style: TextStyle(color: Colors.white),
),
),
onTap: () {},
),
));
}
总感觉有点复杂,InkWell 会导致水纹超出边框,就需要外面再套一层组件,然后还要写个渐变,不知道咋形容。
Listener
Listener 是一个监听指针事件的控件,比如按下、移动、释放、取消等指针事件,但Listener无法监听鼠标特有的事件,比如:移入、悬停、移出事件。鼠标事件使用MouseRegion监听。
通常情况下,监听手势事件使用GestureDetector,GestureDetector是更高级的手势事件。
Listener的事件介绍如下:
onPointerDown:按下时回调
onPointerMove:移动时回调
onPointerUp:抬起时回调
Listener(
onPointerDown: (PointerDownEvent pointerDownEvent) {
print('$pointerDownEvent');
},
onPointerMove: (PointerMoveEvent pointerMoveEvent) {
print('$pointerMoveEvent');
},
onPointerUp: (PointerUpEvent upEvent) {
print('$upEvent');
},
child: Container(
height: 200,
width: 200,
color: Colors.blue,
alignment: Alignment.center,
),
)
常用属性说明如下:
position:相对屏幕的坐标的偏移。
localPosition:相对当前控件的偏移。
pressure:按压力度。
delta:2次指针移动事件的偏移。
orientation:指针移动方向
案例
进度按钮
// 使用枚举定义按钮的状态
enum ButtonStates { none, loading, done }
class YcHomeBody extends StatefulWidget {
const YcHomeBody({Key? key}) : super(key: key);
@override
State<YcHomeBody> createState() => _YcHomeBodyState();
}
class _YcHomeBodyState extends State<YcHomeBody> {
//定义按钮的状态
ButtonStates _buttonStates = ButtonStates.none;
@override
Widget build(BuildContext context) {
return Center(
child: MaterialButton(
color: Colors.blue,
textColor: Colors.white,
minWidth: 200,
height: 40,
//通过自定义方法,根据情况返回相应的组件
child: _build(),
onPressed: () {
//点击按钮后将按钮状态变为加载中
setState(() {
_buttonStates = ButtonStates.loading;
//延迟2s后将状态变为完成
Future.delayed(const Duration(seconds: 2), () {
setState(() {
_buttonStates = ButtonStates.done;
});
});
});
},
),
);
}
//自定义方法
_build() {
if (_buttonStates == ButtonStates.none) {
//无状态
return const Text("登录");
} else if (_buttonStates == ButtonStates.loading) {
//进度条组件
return const CircularProgressIndicator(
backgroundColor: Colors.white,
strokeWidth: 2,
);
} else if (_buttonStates == ButtonStates.done) {
return const Icon(
Icons.check,
color: Colors.white,
);
}
}
}
代码看着很长但是逻辑很简单,定义了一个枚举类型的按钮类型。一开始类型为无状态,此时显示登录;当点击按钮后,状态变为加载中,显示圆形进度条组件;2s后将按钮状态变为加载完成,现成完成的图标
来源:https://blog.csdn.net/weixin_41897680/article/details/127778262


猜你喜欢
- 废话不多说,咱们第一篇文章就是模仿“知乎”的回答详情页的动画效果,先上个原版的效果图,咱们就是要做出这个效果 &nbs
- 本文实例讲述了C#画图之饼图折线图的实现方法,是C#程序设计中非常实用的技巧。分享给大家供大家参考。具体方法分析如下:显示图像的控件定义如下
- 快速排序实现: namespace QuickSort { class QuickSort { public static void Sor
- 学习完数组就能用C语言写出的简单小游戏:编译器使用的为VS2013代码分为三个部分1、头文件 game.h2、源文件 game.c 用来存放
- 因为项目不同,有些公用库而且还是c++的,还有一些带资源的,简单的复制遇到库升级又是一轮配置,编译成aar则解决这些麻烦。但是默认andri
- 把C#编译成DLL或者Axtive控件,再由C调用!比如使用C++调用C#的DLL。SwfDotNet是.net下输出flash的类库。Sw
- 一、synchronized 有不足新事物的出现要不是替代老事物,要么就是对老事物的补充JUC 的 locks 就是对 synchroniz
- 1.写个Mybatis-plus配置类:是通过 * 实现分页@Configurationpublic class MybatisConfig
- 本文实例为大家分享了Android实现摄像头切换,拍照及保存到相册,预览等功能,解决android7拍照之后不能连续预览的问题、参数设置相关
- 目录设置应用的名称,包名、应用图标和启动替换应用图标替换启动页设置访问权限配置版本发布参数生成应用签名修改配置文件打包注意事项设置应用的名称
- 软件需求VS2019社区版、win10操作系统、opencv4.1.0VS2019社区版(免费) 下载地址OpenCV4.1.0 下载地址配
- 利用栈实现一个简易计算器(Java实现),供大家参考,具体内容如下一、思路分析当我们输入一个类似于“7*2+100-5+
- 1.@RequestMapping的介绍通过@RequestMapping,我们可以把请求地址和方法进行绑定的,可以在类、方法上进行声明。类
- 为了防止,页面向数据库暴力注册入力,用户登录暴力破解,所以加入验证码,验证码无法被软件获取上边的内容(加入算数计算,更加安全),所以在现在技
- 对于现在的 App 来说,布局页面基本都会用到沉浸式状态栏,单纯的沉浸式状态栏很容易解决,但是在华为手机上存在一个底部虚拟按键的问题,会导致
- DropDownList控件又称下拉列表框控件, 控件 列表 中的多行数 据 以隐含 的形式表 示 出 来,当用户需要选择所需列表项时,通过
- Java读取txt文件内容。可以作如下理解:首先获得一个文件句柄。File file = new File(); file即为文件句柄。两人
- 前言最近写了一篇博客是关于 使用Jenkins来构建SVN+Maven项目 ,这里使用的的代码版本工具是SVN,但是事实上也有很多公司使用G
- 对HDFS上的文件进行上传和下载是对集群的基本操作,在《HADOOP权威指南》一书中,对文件的上传和下载都有代码的实例,但是对如何配置HAD
- 最近开发过程中遇到了一个问题,之前没有太注意,这里记录一下。我用的SpringBoot版本是2.0.5,在跟前端联调的时候,有个请求因为用户