概述
App Inventor 2的Canvas和Screen只有基本的Touch/Dragged/Fling事件。手势识别扩展(GestureDetector)可以识别更丰富的手势:
| 手势 | 内置支持 | 扩展支持 |
|---|---|---|
| 单击 | ✅ Touched | ✅ |
| 双击 | ❌ | ✅ onDoubleTap |
| 长按 | ❌ | ✅ onLongPress |
| 滑动 | ✅ Flung | ✅ onFling(更精确) |
| 缩放(捏合) | ❌ | ✅ onScale |
| 滚动 | 部分(Dragged) | ✅ onScroll |
| 多点触控 | ❌ | ✅ Multitouch扩展 |
已有文档参考
other/extensionsGestures.md— 手势扩展基础文档other/extensionsMultitouch.md— 多点触控扩展other/extensionsRotation.md— 旋转手势扩展
本文在已有文档基础上,补充具体的使用场景和集成方案。
GestureDetector扩展
导入扩展
- 下载 GestureDetector扩展(.aix文件)
- Designer → Extension → Import Extension → 选择.aix
核心事件
当 GestureDetector1.双击(X, Y)
' 双击触发
标签_状态.文本 = "双击 @ " & X & "," & Y
当 GestureDetector1.长按(X, Y)
' 长按触发
标签_状态.文本 = "长按 @ " & X & "," & Y
当 GestureDetector1.滑动(起点X, 起点Y, 终点X, 终点Y, 速度X, 速度Y)
' 滑动方向判断
设 dX = 终点X - 起点X
设 dY = 终点Y - 起点Y
如果 数学.绝对值(dX) > 数学.绝对值(dY)
如果 dX > 0
标签_状态.文本 = "👉 右滑"
否则
标签_状态.文本 = "👈 左滑"
否则
如果 dY > 0
标签_状态.文本 = "👇 下滑"
否则
标签_状态.文本 = "👆 上滑"
关联组件
GestureDetector需要关联到一个可视组件(如Canvas或Image):
当 Screen1.初始化
调用 GestureDetector1.设置目标组件(Canvas1)
实战案例:图片浏览器手势
功能
- 左右滑动切换图片
- 双击放大/缩小
- 长按保存图片
- 上下滑动显示/隐藏工具栏
设 图片列表 = ["pic1.png", "pic2.png", "pic3.png", "pic4.png"]
设 当前索引 = 1
设 是否放大 = false
当 Screen1.初始化
调用 GestureDetector1.设置目标组件(Image1)
设 Image1.图片 = 列表第1项(图片列表)
当 GestureDetector1.滑动(起点X, 起点Y, 终点X, 终点Y, 速度X, 速度Y)
设 dX = 终点X - 起点X
如果 数学.绝对值(dX) > 50 ' 滑动距离阈值
如果 dX > 0 且 当前索引 > 1
设 当前索引 = 当前索引 - 1
设 Image1.图片 = 列表第当前索引项(图片列表)
否则 如果 dX < 0 且 当前索引 < 列表长度(图片列表)
设 当前索引 = 当前索引 + 1
设 Image1.图片 = 列表第当前索引项(图片列表)
标签_页码.文本 = 当前索引 & "/" & 列表长度(图片列表)
当 GestureDetector1.双击(X, Y)
如果 是否放大
设 Image1.宽度 = 90 百分比
设 Image1.高度 = 自动
设 是否放大 = false
否则
设 Image1.宽度 = 200 百分比
设 Image1.高度 = 200 百分比
设 是否放大 = true
当 GestureDetector1.长按(X, Y)
调用 文件工具.保存到相册(Image1.图片)
调用 通知.显示信息("已保存", "图片已保存到相册")
实战案例:手势密码锁
功能
- 在Canvas上画手势路径
- 记录触摸经过的格子
- 验证手势密码
设 网格大小 = 3 ' 3x3网格
设 格子坐标 = 创建空列表
设 手势路径 = 创建空列表
设 正在画 = false
设 正确密码 = "1-2-3-6-9" ' 示例密码路径
当 Screen1.初始化
' 计算格子中心坐标
设 格子宽 = Canvas1.宽度 / 网格大小
设 格子高 = Canvas1.高度 / 网格大小
设 i = 0
当 i < 9
设 行 = 数学.向下取整(i / 网格大小)
设 列 = i 模 网格大小
设 中心X = 列 * 格子宽 + 格子宽 / 2
设 中心Y = 行 * 格子高 + 格子高 / 2
设 格子坐标 = 添加列表项(格子坐标, 创建字典("id" → (i+1), "x" → 中心X, "y" → 中心Y))
设 i = i + 1
绘制网格()
当 Canvas1.触摸(触摸, X, Y)
设 正在画 = true
设 手势路径 = 创建空列表
调用 检查格子(X, Y)
当 Canvas1.拖动(被拖动, 起X, 起Y, 当X, 当Y, 上X, 上Y)
如果 被拖动
调用 检查格子(当X, 当Y)
' 画线连接
调用 Canvas1.画线(上X, 上Y, 当X, 当Y)
定义 检查格子(X, Y)
设 i = 1
当 i ≤ 列表长度(格子坐标)
设 格子 = 列表第i项(格子坐标)
设 格X = 从字典 格子 获取 "x"
设 格Y = 从字典 格子 获取 "y"
设 格ID = 从字典 格子 获取 "id"
设 距离 = 数学.平方根((X-格X)^2 + (Y-格Y)^2)
如果 距离 < 40 且 非 (格ID 是否在 手势路径 中)
设 手势路径 = 添加列表项(手势路径, 格ID)
' 高亮选中的格子
调用 Canvas1.画圆(格X, 格Y, 30, 绿色)
设 i = i + 1
当 按钮_验证.被点击
设 路径文本 = 列表转文本(手势路径, "-")
如果 路径文本 = 正确密码
标签_结果.文本 = "✅ 密码正确"
调用 打开另一个屏幕("Screen_Main")
否则
标签_结果.文本 = "❌ 密码错误"
Multitouch多点触控
参考已有文档 other/extensionsMultitouch.md,此处补充关键用法:
设 手指计数 = 0
当 Multitouch1.触摸开始(指针ID, X, Y)
设 手指计数 = 手指计数 + 1
标签_手指.文本 = "触摸点:" & 手指计数
当 Multitouch1.触摸移动(指针ID, X, Y)
' 多指拖拽处理
如果 手指计数 = 2
' 双指缩放
设 距离 = 计算两点距离(手指1X, 手指1Y, 手指2X, 手指2Y)
设 缩放比 = 距离 / 初始距离
设 Image1.宽度 = 初始宽度 * 缩放比
当 Multitouch1.触摸结束(指针ID, X, Y)
设 手指计数 = 手指计数 - 1
常见问题
Q1: 手势扩展和Canvas事件冲突?
设置优先级:手势扩展和Canvas事件可能同时触发。解决:
- 用手势扩展处理复杂手势(双击、长按)
- 用Canvas事件处理绘制相关
- 设置标志变量控制
Q2: 手势识别灵敏度如何调整?
大多数手势扩展有阈值参数:
CONFIRM_THRESHOLD— 确认阈值VELOCITY_THRESHOLD— 速度阈值- 根据实际体验微调
Q3: 如何实现下拉刷新?
当 GestureDetector1.滑动(起点X, 起点Y, 终点X, 终点Y, 速度X, 速度Y)
设 dY = 终点Y - 起点Y
如果 dY > 100 且 速度Y > 500 ' 下拉距离够且速度够
' 触发刷新
调用 刷新数据()
总结
| 手势 | 方案 | 推荐扩展 |
|---|---|---|
| 单击 | 内置Touched | 不需要 |
| 双击 | GestureDetector | GestureDetector |
| 长按 | GestureDetector | GestureDetector |
| 滑动方向 | 内置Flung或扩展 | GestureDetector |
| 缩放 | Multitouch | Multitouch |
| 旋转 | Rotation扩展 | Rotation |
| 多指 | Multitouch | Multitouch |
版权声明:MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权,本文档由 ai2claw 🐝 整理。
扫码添加客服咨询