上一篇介绍了单点触摸, android 自2.0 开始引入多点触摸的支持.
分以下几部分
1. android 2.2之前的多点触摸
2 自 2.2 开始的多点触摸
在2.2中,淘汰了两个常量,ACTION_POINTER_ID_MASK, ACTION_POINTER_ID_SHIFT。当多根手指触摸屏幕时,MotionEvent 对象必须包含来自所有手指的信息,需要了解的第一个方法 是 getPointerCount(), 表示多少根手指, 这里涉及到 指针索引(手指数目, 从0 开始) 和指针 ID(第几根手指,也从0开始).
要理解这样的情景: 想象两根手指的触摸序列,从手指1 按下开始,然后手指 2按下,然后手指1离开,最后手指2离开.手指1 将获得指针 ID 0, 手指2获得指针 ID 1, 第一根手指离开以后,手指2 将仍然与指针 ID 1关联。但手指2 的指针索引变为 0,因为指针索引始终从0 开始.
看一个示例, 主要代码如下:
protected static String describeEvent(MotionEvent event) {
StringBuilder result = new StringBuilder(500);
result.append("Action: ").append(event.getAction()).append("\n");
int numPointers = event.getPointerCount();
result.append("手指数量: ").append(numPointers).append("\n");
int ptrIdx = 0;
while (ptrIdx < numPointers) {
int ptrId = event.getPointerId(ptrIdx);
result.append("手指数目: ").append(ptrIdx);
result.append(", 第 : ").append(ptrId).append(" 根手指 \n");
result.append(" Location: ").append(event.getX(ptrIdx));
result.append(" x ").append(event.getY(ptrIdx)).append("\n");
result.append(" 压力 : ").append(event.getPressure(ptrIdx));
result.append(" 触摸面积: ").append(event.getSize(ptrIdx)).append("\n");
ptrIdx++;
}
result.append("Downtime: ").append(event.getDownTime()).append("ms\n");
result.append("Event time: ").append(event.getEventTime()).append("ms");
result.append(" Elapsed: ");
result.append(event.getEventTime()-event.getDownTime());
result.append(" ms\n");
return result.toString();
}
private void logAction(MotionEvent event) {
int action = event.getAction();
int ptrIndex = (action & MotionEvent.ACTION_POINTER_ID_MASK) >>> MotionEvent.ACTION_POINTER_ID_SHIFT;
action = action & MotionEvent.ACTION_MASK;
if(action == 5 || action == 6)
action = action - 5;
int ptrId = event.getPointerId(ptrIndex);
Log.e("Action", "Pointer index: " + ptrIndex);
Log.e("Action", "Pointer Id: " + ptrId);
Log.e("Action", "True action value: " + action);
}
效果图
具体代码请参见 ch25_MultiTouchDemo1 工程
android2.2 开始的多点触摸 示例代码 请参见 ch25_MultiTouchDemo2 工程
3 触摸地图
用于地图的一个主要类是 MapView,它具有一个onTouchEvent() 方法;其他主要的对象类型是各种Overlay, 包括ItemizedOverlay 和 MyLocationOverlay
MapView 提供了一个名为Projection 的接口,Projection 接口有 在像素与GeoPoint 之间相互转换的方法
4 手势 (Gesture)
下面介绍手势, 手势是一类特殊的触摸屏事件, 通俗理解为手写输入
手势需要一个覆盖图,该覆盖图可以检测用户的手势并将它传递给基础活动,
分别作以下介绍
(1) 捏合手势, 用于实现缩放,通常应用于图像,可能是地图.
捏合必须在真机上实现(因为只有真机才能感应多点触摸)
捏合手势在 2.2 版以前没有得到 明确的支持,所以要实现必须自行创建代码来读取事件对象并采取适当的操作,主要通过onTouchEvent() 实现,
自2.2 版以后,无需开发人员执行任何操作即可支持捏合缩放, 它是开箱的,这里首先介绍一个类:GestureDetector (手势探测)
它的用途是接收 MotionEvent对象并在一个事件序列看起来像一个 常用手势 时通知我们, 开发者通过回调将所有事件对象传递 给 GestureDetector, 然而遗憾的是,此类没有告诉开发者是否发生了捏合手势。
从2.2开始, 引入了ScaleGestureDetector 类, 这是确定捏合手势的类. 并有相应的监听器类SimpleOnScaleGestureListener
相关代码请参见 ch25_ScaleDetector 工程, 示例运行后示意图如下