Android手勢:單指拖動、雙指縮放圖片
手勢其實是一個比較複雜的東西,首先是因為處理的時機。Android中觸控式螢幕的事件其實只有ACTION_DOWN、ACTION_MOVE和 ACTION_UP這三種,當然我們實現手勢的邏輯時,一般會用到GestureDetector,它有許多封裝好的事件回撥介面,比如onFling、 onLongPress、onScroll等,其實這些事件只是對上面那三個基本時間的包裝而已:即三個基本事件按一定的序列出現,則會觸發響應的 GestureDetector中的事件,比如ACTION_DOWN 加上三個ACTION_MOVE再加上ACTION_UP就是一次Fling事件等等。
雖然手勢能給使用者帶來比較新奇好玩的體驗,GestureDetector這樣的介面很容易理解,但是卻也有很多問題,主要是自定義手勢時。假如我們要實現一個自定義的手勢,即當用戶在觸控式螢幕上畫圓時響應我們的事件處理邏輯,那麼當用戶畫圓時,其實也是一個Scroll事件,這時候就不太好確定到底響應畫圓事件還是Scroll事件了。
手勢帶來的另一個問題是UI的體驗,大多數情況下我們需要考慮到使用者手指移動的加速度、反饋、期望等,比如快速的滑動和低速的滑動給使用者的心理預期是完全不同的,這方面做得比較完美的要數MacBook上的TouchPad了,從單指移動滑鼠、雙指視窗內移動,到三指視窗間切換、四指返回Home,給使用者的體驗算是十分優秀的了。當然這都是互動的內容了,不再過多討論,一般產品中也不建議做太複雜的手勢。
一般情況下我們用的比較多的手勢就是單指拖拽、雙指縮放圖片這樣的簡單手勢,下面的程式碼是ImageView實現單指和雙指這兩種手勢的程式碼,沒有用到GestureDetector,而是僅僅對onTouch事件進行處理:
注:ImageView 中要新增 android:scaleType="matrix"
float last_x = -1;
float last_y = -1;
mImage.setOnTouchListener(new OnTouchListener() {
float baseValue;
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
// return ArtFilterActivity.this.mGestureDetector.onTouchEvent(event);
baseValue = 0;
float x = last_x = event.getRawX();
float y = last_y = event.getRawY();
}
else if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (event.getPointerCount() == 2) {
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
float value = (float) Math.sqrt(x * x + y * y);// 計算兩點的距離
if (baseValue == 0) {
baseValue = value;
}
else {
if (value - baseValue >= 10 || value - baseValue <= -10) {
float scale = value / baseValue;// 當前兩點間的距離除以手指落下時兩點間的距離就是需要縮放的比例。
img_scale(scale); //縮放圖片
}
}
}
else if (event.getPointerCount() == 1) {
float x = event.getRawX();
float y = event.getRawY();
x -= last_x;
y -= last_y;
if (x >= 10 || y >= 10 || x <= -10 || y <= -10)
img_transport(x, y); //移動圖片位置
last_x = event.getRawX();
last_y = event.getRawY();
}
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});