在上一篇文章中,淺談Android 事件分發機制(一),簡要分析了一下事件分發機制的原理,總結一下就是事件層層傳遞,直到被消費,原理看似簡單,但是在實際使用過程中,場景各不相同,複雜程度也就因產品而異,這篇文章就通過給view加移動來模擬事件分發。
這裡涉及到幾個與手指觸摸相關的常見事件:
坐標系對於單指觸控移動來說,一次簡單的交互流程是這樣的:
Android坐標系以手機屏幕左上角的頂點為坐標原點,從該點向右為x軸正方向,從該點向下為y軸正方向。 上圖所示,一次觸摸涉及到多種距離的計算, 上圖所標註的方法可以分為兩類,一類是View提供的方法,一類是MotionEvent提供的方法。
View提供的:
getTop()
getLeft()
getRight()
getBottom()
MotionEvent提供的方法:
getX()
getY(): 獲取觸摸點距離控制項頂邊的距離,即視圖坐標
getY()
getRawX()
getRawY()
給ViewC(藍色區域)添加移動
onTouchEvent
MotionEvent.ACTION_DOWN
lastX
lastY
MotionEvent.ACTION_MOVE
x
y
layout
MotionEvent.ACTION_UP
margin
private int lastX; private int lastY; @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastX = x; lastY = y; break; case MotionEvent.ACTION_MOVE: //計算移動的距離 int offsetX = x - lastX; int offsetY = y - lastY; int l = getLeft() + offsetX; int b = getBottom() + offsetY; int r = getRight() + offsetX; int t = getTop() + offsetY; //重新確認位置 layout(l, t, r, b); break; case MotionEvent.ACTION_UP: LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams(); params.setMargins(getLeft(), getTop(), 0, 0); break; default: break; } return true; }
同樣給ViewGroupB添加以上的代碼用於B的移動。(藍色的視圖C,黃色的視圖B)
ViewGroupB
情況一:如上圖 這裡視圖B、C的onTouchEvent都返回true,在C區域滑動,viewC消費了事件,不再傳遞給B;只有在B、C不重疊的區域滑動,C才會移動,這時沒有接觸到C,所以不會觸發C的事件。因為我們在C的MotionEvent.ACTION_UP手指離開時固定了C到父布局(B)的距離,所以C相對B的位置沒變。
viewC
情況二:如上圖,將C的onTouchEvent返回false,在C區域滑動,事件沒有消費,傳遞給到了B,B可以滑動,在不重疊區域一樣可以滑動B。
onInterceptTouchEvent
推薦閱讀:
TAG:Android | Android開發 | Android應用 |