android单点触摸事件,Android多点触控详解
最近需要做個Android的項目,需要使用多點觸控的功能,上網找了很久,中文方面的資料相當少,英文方面也不多,經過自己的研究,加上對已知的一些資料的整理,下面為大家介紹一下Android多點觸控程序的編寫。
首先,我們準備好一張圖片:
在Eclipse下新建一個Android工程(和一般Android工程一樣),需要注意的是:Android的多點觸控功能需要運行在Android 2.0版本以上。
完成后,我們需要將原先準備好的圖片放進res/drawable文件夾下(注意,如果是Android2.2,請放在三個drawable文件夾下),如圖所示:
該圖片是為了給該多點觸控的實例提供運行環境,實現圖片的放大和縮小。下面,我們來修改一下main.xml文件,如下所示:<?xml version="1.0" encoding="utf-8"?>
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="@drawable/img"
android:scaleType="matrix" >
對于讓一張靜態圖片在Android面板上顯示,我們可以采用下面的一句話:ImageView imageView = (ImageView)findViewById(R.id.imageView);
通過設置Matrix,我們可以獲得對ImageView的一些基本操作。
OK,啰嗦這么多,下面進入主題:
我們需要實現一個OnTouchListener的方法,來設置ImageView的偵聽屬性,該接口位于android.view.View.OnTouchListener。
實現onTouch(View view, MotionEvent event)的方法,就可以獲取觸屏的感應事件了。
在該事件中,有兩個參數可以用來獲取對觸摸的控制,這兩個參數分別
為:MotionEvent.getAction()和MotionEvent.ACTION_MASK,前者用于對單點觸控進行操作,后者用于對多點觸
控進行操作,相應地,我們可以通過Android Developers’
Reference看到,對于單點觸控,我們由MotionEvent.getAction()可以得到以下幾種事件:ACTION_DOWN、
ACTION_UP,而對于多點觸控,由MotionEvent.ACTION_MASK,我們可以得到:ACTION_POINTER_DOWN、
ACTION_POINTER_UP,都是MotionEvent中的常量,可以直接調用。而有些常量則是單點和多點共用的,
如:ACTION_MOVE,因此在按下時,我們必須標記單點與多點觸控的區別。
下面我們來介紹一下縮放功能的實現,對于縮放,我們定義有兩種手勢,一種是雙指拉伸式,一種是單指旋轉式。
首先,雙指拉伸式。
這是一種比較常規的圖片縮放方式,實現起來也比較方便,我們可以很容易想到,在處理多點觸控事件時,如果沒有別的手勢干擾,我們只需檢測兩指按下時和移動之后的位置關系即可,如果距離變大,則是放大圖片;反之則是縮小圖片。
主要代碼如下:
if(mode == ZOOM)
{
float newDistance;
newDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));
if(newDistance > 10f) {
matrix.set(savedMatrix);
matrix.postScale(newDistance/oldDistance, newDistance/oldDistance, mid.x, mid.y);
oldDistance = newDistance;
savedMatrix.set(matrix);
}
}
然后,單指旋轉式。
這是一種單指操作中比較流行的方式,然而實現起來并非特別方便。具體說來,我們可以定
義順時針轉動為圖片放大,逆時針轉動為圖片縮小。在沒有其他干擾項的時候,我們可以通過捕獲三次連續移動來得知手勢順時針還是逆時針。如下圖所示,我們把
前兩次的位置作一個向量A,后兩次位置作一個向量B,如果向量B比向量A大,則是逆時針;向量B比向量A小則是順時針。當然,我們這里就要用到反三角函
數,同時要注意2pi的角度問題哦~
注意:在處理同為單指操作或者同為多指操作的時候,要考慮不同行為之間的區別。
主要代碼如下:if (mode == MOVE)
{
if(rotate == NONE) {
savedMatrix.set(matrix);
mid.set(event.getX(), event.getY());
rotate = ROTATION;
}
else {
matrix.set(savedMatrix);
double a = Math.atan((mid.y-start.y)/(mid.x-start.x));
double b = Math.atan((event.getY()-mid.y)/(event.getX()-mid.x));
if ((b - a < Math.PI/2 && b - a > Math.PI / 18)||((b + Math.PI) % Math.PI - a < Math.PI/2 && (b + Math.PI) % Math.PI - a > Math.PI / 18)) {
matrix.postScale((float)0.9, (float)0.9);
}
else if ((a - b < Math.PI / 2 && a - b > Math.PI / 18)||((a + Math.PI) % Math.PI - b < Math.PI/2 && (a + Math.PI) % Math.PI - b > Math.PI / 18)) {
matrix.postScale((float)1.1, (float)1.1);
}
start.set(event.getX(), event.getY());
rotate = NONE;
}
}
下面是實現的結果截圖:
初始畫面:
通過鼠標順時針轉動后的效果圖:
通過鼠標逆時針轉動后的效果圖:
下面是代碼的具體解析:
TouchActivity.javapackage example.MultiTouch;
import android.app.Activity;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
public class TouchActivity extends Activity {
private static final int NONE = 0;
private static final int MOVE = 1;
private static final int ZOOM = 2;
private static final int ROTATION = 1;
private int mode = NONE;
private Matrix matrix = new Matrix();
private Matrix savedMatrix = new Matrix();
private PointF start = new PointF();
private PointF mid = new PointF();
private float s = 0;
private float oldDistance;
private int rotate = NONE;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView imageView = (ImageView)findViewById(R.id.imageView);
imageView.setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View view, MotionEvent event) {
ImageView imageView = (ImageView)view;
switch (event.getAction()&MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = MOVE;
rotate = NONE;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
case MotionEvent.ACTION_POINTER_DOWN:
oldDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));
if (oldDistance > 10f) {
savedMatrix.set(matrix);
mid.set((event.getX(0)+event.getX(1))/2, (event.getY(0)+event.getY(1))/2);
mode = ZOOM;
}
case MotionEvent.ACTION_MOVE:
if (mode == MOVE)
{
if(rotate == NONE) {
savedMatrix.set(matrix);
mid.set(event.getX(), event.getY());
rotate = ROTATION;
}
else {
matrix.set(savedMatrix);
double a = Math.atan((mid.y-start.y)/(mid.x-start.x));
double b = Math.atan((event.getY()-mid.y)/(event.getX()-mid.x));
if ((b - a < Math.PI/2 && b - a > Math.PI / 18)||((b + Math.PI) % Math.PI - a < Math.PI/2 && (b + Math.PI) % Math.PI - a > Math.PI / 18)) {
matrix.postScale((float)0.9, (float)0.9);
}
else if ((a - b < Math.PI / 2 && a - b > Math.PI / 18)||((a + Math.PI) % Math.PI - b < Math.PI/2 && (a + Math.PI) % Math.PI - b > Math.PI / 18)) {
matrix.postScale((float)1.1, (float)1.1);
}
start.set(event.getX(), event.getY());
rotate = NONE;
}
}
else if(mode == ZOOM)
{
float newDistance;
newDistance = (float)Math.sqrt((event.getX(0)-event.getX(1))*(event.getX(0)-event.getX(1))+(event.getY(0)-event.getY(1))*(event.getY(0)-event.getY(1)));
if(newDistance > 10f) {
matrix.set(savedMatrix);
matrix.postScale(newDistance/oldDistance, newDistance/oldDistance, mid.x, mid.y);
oldDistance = newDistance;
savedMatrix.set(matrix);
}
}
break;
}
imageView.setImageMatrix(matrix);
return true;
}
});
}
}
AndroidManifest.xml<?xml version="1.0" encoding="utf-8"?>
package="example.MultiTouch"
android:versionCode="1"
android:versionName="1.0">
android:label="@string/app_name">
總結
以上是生活随笔為你收集整理的android单点触摸事件,Android多点触控详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: step1:准备歌词之《前端开发是个啥》
- 下一篇: 第十二章 国民收入的决定:AD-AS模型