Android多点触控在本质上需要LCD驱动和程序本身设计上支持,目前市面上只要使用电容屏触控原理的手机均可以支持多点触控Multitouch技术,对于网页缩放、手势操作上有更好的用户体验。 在Android平台上事件均使用了MotionEvent对象方式处理,比如开始触控时会触发ACTION_DOWN而移动操作时为 ACTION_MOVE最终放开手指时触发ACTION_UP事件。当然还有用户无规则的操作可能触发ACTION_CANCEL这个动作.
对于常规的控件触控操作在内部为View的setOnTouchListener()接口实现的 onTouchEvent()方法来处理。
下面用ImageView做演示:
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView android:id="@+id/imageView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/pic"
android:scaleType="matrix" >
</ImageView>
</FrameLayout>
java文件:
package com.shao.muti;
import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
public class MutiTouchActivity extends Activity implements OnTouchListener{
/** Called when the activity is first created. */
private static final String TAG="Touch";
private static final int NONE= 0 ;
private static final int DRAG = 1;
private static final int ZOOM =2;
int mode = NONE;
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView view = (ImageView) findViewById(R.id.imageView);
view.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
ImageView view = (ImageView) v;
printEventinfo(event);//测试输出信息
switch(event.getAction()&MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
//設置初始點位置
start.set(event.getX(),event.getY());
Log.d(TAG,"mode=DRAG");
mode =DRAG;
break;
case MotionEvent.ACTION_POINTER_1_DOWN:
oldDist= spacing(event);
Log.d(TAG,"lodDist="+oldDist);
if(oldDist>10f){
savedMatrix.set(matrix);
midPoint(mid,event);
mode = ZOOM;
Log.d(TAG,"mode=ZOOM");
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_1_UP:
mode =NONE;
Log.d(TAG,"mode=NONE");
break;
case MotionEvent.ACTION_MOVE:
if(mode==DRAG){
matrix.set(savedMatrix);
matrix.postTranslate(event.getX()-start.x, event.getY()-start.y);
}
else if(mode == ZOOM){
float newDist = spacing(event);
Log.d(TAG, "newDist=" + newDist);
if (newDist > 10f) {
matrix.set(savedMatrix);
float scale = newDist / oldDist;
matrix.postScale(scale, scale, mid.x, mid.y);
}
}
break;
}
view.setImageMatrix(matrix);
return true;
}
private void printEventinfo(MotionEvent event){
int num =0;
System.out.println("触控动作---->"+event.getAction()); //获取触控动作比如ACTION_DOWN
System.out.println("取触控点的数量--->"+event.getPointerCount()); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕
num = event.getPointerCount();
for(int i=0;i<num;i++){
System.out.println("索引-->"+event.getPointerId(i)); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引
System.out.println("第i个触控点的x位置-->"+event.getX(i)); //获取第i个触控点的x位置
System.out.println("第i个触控点的y位置-->"+event.getY(i)); //获取第i个点触控的y位置
System.out.println("手指压力-->"+event.getPressure(i)); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的
}
System.out.println("开始时间"+event.getDownTime()); //按下开始时间
System.out.println(" 事件结束时间"+event.getEventTime()); // 事件结束时间
System.out.println("总共按下时花费时间"+(event.getEventTime()-event.getDownTime())); //总共按下时花费时间
}
/** Determine the space between the first two fingers */
private float spacing(MotionEvent event){
float x = event.getX(0)-event.getY(1);
float y = event.getY(0)-event.getY(1);
return (float)Math.sqrt(x*x+y*y);
}
/** Calculate the mid point of the first two fingers */
private void midPoint(PointF point, MotionEvent event) {
float x = event.getX(0) + event.getX(1);
float y = event.getY(0) + event.getY(1);
point.set(x / 2, y / 2);
}
}