1. 程式人生 > >初步解析View的滑動

初步解析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);