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>
要注意的是 android:scaleType 的属性必须设置为matrix,否则图片无法改变大小。
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); } }