歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Android 多點觸摸

Android 多點觸摸

日期:2017/3/1 11:15:49   编辑:Linux編程
其實多點觸摸並沒有想象中的那麼神奇。處理2個手指一般就已經夠用,放上3個手指顯得有點滑稽,依賴更多手指進行操作絕對不是一個好的主意。 理論上Android可以處理 多達256 個手指的觸摸,大概只有章魚哥能享受這種技術帶來的便利。就編程人員來說,編寫多點觸摸和單點觸摸的方式幾乎一模一樣。其奧秘在於MotionEvent不僅可以封裝單點觸摸的消息,也可以封裝多點觸摸的消息。

在處理單點觸摸中,我們用到MotionEvent.ACTION_DOWN、ACTION_UP、ACTION_MOVE,然後用一個Switch來分別進行處理。翻開Android文檔,我們就可以清楚的知道他們都是一些常量。

ACTION_DOWN 0x00000000 ACTION_UP 0x00000001 ACTION_MOVE 0x00000002
細心看看文檔發現還有一些別的常量:
ACTION_POINTER_1_DOWN 0x00000005 ACTION_POINTER_1_UP 0x00000006
ACTION_POINTER_2_DOWN 0x00000105 ACTION_POINTER_2_UP 0x00000106
ACTION_POINTER_3_DOWN 0x00000205 ACTION_POINTER_3_UP 0x00000206

這些常量正是我們用來處理多點觸摸的工具。

public class MultiTouchActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}

@Override
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();

switch(action){
case MotionEvent.ACTION_POINTER_1_DOWN:
showMessage("第一個手指按下");
break;
case MotionEvent.ACTION_POINTER_1_UP:
showMessage("第一個手指抬起");
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
showMessage("第二個手指按下");
break;
case MotionEvent.ACTION_POINTER_2_UP:
showMessage("第二個手指抬起");
break;
case MotionEvent.ACTION_POINTER_3_DOWN:
showMessage("第三個手指按下");
break;
case MotionEvent.ACTION_POINTER_3_UP:
showMessage("第三個手指抬起");
break;
}
return true;

}
private void showMessage(String s){
Toast toast = Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT);
toast.show();
}
}
上面的代碼和我們處理單點觸摸的方式一模一樣。借助這個小小的例子,我們看看Android產生多點消息的機制。
情況一:手指1 按下 沒有出現提示; 手指1 抬起 也沒有出現提示;
這是很顯然的,因為這時產生的消息是ACTION_DOWN 和 ACTION_UP。
情況二:手指1按下 沒有提示;
手指2按下 出現手指2按下的提示;手指2抬起 出現手指2抬起的提示。
情況三:手指1 按下 沒有提示;
手指2 按下 出現提示;
這時 手指1 提起 出現手指1提起的提示;手指1按下 出現手指1按下的提示;
情況四:大家可以放三個手指去嘗試下,看看Android 是怎樣產生這些消息的。
根據我們實驗的結果,可以得到一句話:當屏幕上有一個手指時 可以完美的產生2點觸摸的消息。 當屏幕上有2個手指時可以完美的產生3點觸摸消息,以此類推……。所謂的完美就是指你能正確的得到到底是那個手指進行了操作。
這只是一個小小的深入,我們查看文檔時,並沒有發現ACTION_POINTER_2_MOVE這樣的常量。當第二個手指移動時,我們怎麼處理這種事件呢?其實,這樣的事件常量都是有規律的單點觸摸時DOWN 的最後兩位是00,UP是01,MOVE是02.多點觸摸時,DOWN是05,UP是06, 你可以猜猜MOVE會不會是07呢?再者,POINTER_1 的34位是00,POINTER_2的34位是01,POINTER_3是02。我們幾乎可以肯定的說所謂的ACTION_POINTER_2_MOVE就是0x00000107了。

public class Pointer2DrawActivity extends Activity {
/** Called when the activity is first created. */
ImageView imgView;
Bitmap bitmap;
Canvas canvas;
Paint paint;
private static final int ACTION_POINTER_2_MOVE = 0x00000107;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgView = (ImageView)findViewById(R.id.imgView);
Display currentDisplay = getWindowManager().getDefaultDisplay();
float dw = currentDisplay.getWidth();
float dh = currentDisplay.getHeight();
bitmap = Bitmap.createBitmap((int)dw, (int)dh, Config.ARGB_8888);
canvas = new Canvas(bitmap);
paint = new Paint();
paint.setColor(Color.GREEN);
imgView.setImageBitmap(bitmap);
}
@Override
public boolean onTouchEvent(MotionEvent event){
int action = event.getAction();
float x = 0;
float y = 0;
if(action == ACTION_POINTER_2_MOVE){
x = event.getX();
y = event.getY();
canvas.drawPoint(x, y, paint);
imgView.invalidate();
}
return true;
}
}

這個神奇的Pointer2Draw想要你的第二個手指繪制一些點。一個手指是什麼也繪制不了的……
前面寫了一個Pointer2Draw的小程序。這個程序的神奇之處在於,你永遠也別想繪制出任何東西。原因是根本沒有所謂 的0x00000107。下面看看如何正確的處理多點觸摸,光靠event.getAction()吃飯的時代已經終結了……

int pointerCount = event.getPointerCount();

int pointerCount = event.getPointerCount();

這個函數具體返回值受到物理設備的限制,我費了很大力氣將十個手指放到了我的手機上,得到的結果仍然是8。
(2)得到手指的ID:Android提供了兩個掩碼方便我們操作ACTION_POINTER_ID_MASK 0x0000ff00,和ACTION_POINTER_ID_SHIFT 0x00000008。

if(pointerCount>1){
pointerId = (action & MotionEvent.ACTION_POINTER_ID_MASK)>>>
MotionEvent.ACTION_POINTER_ID_SHIFT;
}
if(pointerCount>1){
pointerId = (action & MotionEvent.ACTION_POINTER_ID_MASK)>>>
MotionEvent.ACTION_POINTER_ID_SHIFT;
}

(3)利用ID獲得坐標信息:

float x = event.getX(pointerId);//獲得第二個手指的坐標
float y = event.getY(pointerId);

float x = event.getX(pointerId);//獲得第二個手指的坐標
float y = event.getY(pointerId);

下面終於可以讓Pointer2Draw運行起來了。
public class Pointer2DrawActivity extends Activity implements OnTouchListener{
/** Called when the activity is first created. */
ImageView imgView;
Bitmap bitmap;
Canvas canvas;
Paint paint;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
imgView = (ImageView)findViewById(R.id.imgView);
Display currentDisplay = getWindowManager().getDefaultDisplay();
float dw = currentDisplay.getWidth();
float dh = currentDisplay.getHeight();
bitmap = Bitmap.createBitmap((int)dw, (int)dh, Config.ARGB_8888);
canvas = new Canvas(bitmap);
paint = new Paint();
paint.setColor(Color.GREEN);
paint.setStrokeWidth((float) 10.00);//設置筆刷大小,自己的屏幕太犀利了
imgView.setImageBitmap(bitmap);
imgView.setOnTouchListener(this);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
int pointerCount = event.getPointerCount();
int pointerId = 0;
int action = (event.getAction()&MotionEvent.ACTION_MASK) % 5;//統一單點和多點
switch(action){
case MotionEvent.ACTION_DOWN:
if(pointerCount>1){
pointerId = (event.getAction()&MotionEvent.ACTION_POINTER_ID_MASK)>>>
MotionEvent.ACTION_POINTER_ID_SHIFT;
}
break;
case MotionEvent.ACTION_MOVE:
if(pointerCount == 2){
float x = event.getX(1);
float y = event.getY(1);
canvas.drawPoint((int)x, (int)y, paint);
imgView.invalidate();
}
break;
case MotionEvent.ACTION_UP:
break;
}

return true;

}
}

Copyright © Linux教程網 All Rights Reserved