初步解析View的滑動
View的滑動方式有很多,在學習View的滑動之前,我們先了解下View是怎麼定位的。
View座標系
1.View自身座標
-
getTop():獲取自身頂部到父佈局頂部的距離
-
getLeft():獲取View自身左邊到父佈局左邊的距離
-
getRight():獲取View自身到父佈局左邊的距離
-
getBottom():獲取View自身到父佈局頂部的距離
2.確定點選位置座標
當我們點選螢幕時,會觸發點選事件。MotionEvent提供了幾種方法獲取點選座標
- getX():點選事件距離自身View左邊的距離
- getY():點選事件距離自身View頂邊的距離
- getRawX():點選事件距離整個螢幕左邊的距離
- getRawY():點選事件距離整個螢幕頂邊的距離
View的滑動
view的滑動是當點選事件傳遞到View時,記下觸控點,當手指移動時,記錄移動後的座標並計算出偏移量,通過偏移量來改變View的座標。
1.layout()
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; layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); break; } }
2.offsetLeftAndRight()與offsetTopAndBottom()
將ACTION_MOVE中的layout方法替換就行
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
3.LayoutParams
通過改變LayoutParams來改變View 的佈局引數,便改變了View的位置,同樣替換ACTION_MOVE中的程式碼
int offsetX = x - lastX;
int offsetY = y - lastY;
ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();
params.leftMargin = getLeft() + offsetX;
params.topMargin = getTop() + offsetY;
break;
4.scrollTo和scrollBy
scrollTo表示移動到具體的座標點位置,scrollBy表示在原來View的基礎上移動偏移量。需要注意的是,移動的偏移量要取反。因為這兩個方法移動的是其內部的內容。
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
((View)getParent()).scrollBy(-offsetX,-offsetY);
break;
5.Scroller
可以通過Scroller來實現View移動的連續性。Scroller需要與View的computeScroll()方法配合。
scroller = new Scroller(context);
重寫computeScroll方法,系統在呼叫draw()方法時,會呼叫此方法。在該方法中,呼叫父類的scrollTo方法,通過Scroller獲取當前滾動值,滑動一小段距離後,呼叫invalidate()方法進行重繪。
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()) {
offsetLeftAndRight(scroller.getCurrX()-getLeft());
offsetTopAndBottom(scroller.getCurrY()-getTop());
invalidate();
}
}
最後呼叫Scroller中的startScroll方法。
scroller.startScroll(getLeft(),getTop(),-getLeft()+initX,-getTop()+initY,2000);