View的事件體系-View基礎知識

位置參數

View的位置主要由它的四個頂點來決定,分別對應於View的四個屬性:top、left、right、bottom.
其中top是左上角的縱座標,left是左上角的橫座標,right是右下角的橫座標,bottom是右下角的縱座標.(注:這些座標都是相對於父容器所說,爲相對座標)

image.png

View的寬高和座標的關係:

width = right - left;
height = bottom - top;

在代碼中獲取四個位置參數:

top = getTop();
left = getLeft();
right = getRight();
bottom = getBottom();

從3.0之後開始,Android增加了幾個參數:x、y、translationX、translationY,並且都是相對父容器的的座標,其中x和y是View左上角的座標.translationX和translationY是View左上角相對於父容器的偏移量,且默認值都爲0.

left = x - translationX;
top = y - translationY;

注:在View的平移過程中,top和left始終表示的是其原始左上角的位置信息,不會發生改變,改變的是x、y、translationX和translationY.

MotionEvent

典型事件

手指接觸屏幕後所產生的一系列事件中,比較重要的有:

  • ACTION_DOWN 手指剛接觸屏幕
  • ACTION_MOVE 手指在屏幕上移動
  • ACTION_UP 手指擡起的一瞬間
常見事件序列
  • 點擊屏幕後擡起 DOWN -> UP
  • 點擊屏幕後滑動後再擡起 DOWN -> MOVE -> UP
事件信息

通過MotionEvent對象我們可以得到點擊事件發生的x和y座標.

  • getX()、getY() 相對於當前View左上角.
  • getRaw()、getY() 相對於手機屏幕左上角

TouchSlop

什麼是TouchSlop

TouchSlop是系統所能識別出的最小滑動距離.如果手指在屏幕上滑動小於該距離則系統無法將該動作認定爲滑動.
這是一個常量,與設備有關,在不同的設備上這個值可能不同.

獲取TouchSlop
int touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
使用場景

當我們在處理滑動時,可以使用這個常量來進行過濾,當滑動距離小於該值,我們可以認爲未達到滑動距離的臨界值,不認爲它是一次有效的滑動.

VelocityTracker

速度追蹤,用於追蹤手指在滑動過程中的速度,包括水平速度和豎直方向的速度.

使用過程

在View的onTouchEvent方法中追蹤當前單擊事件的的速度:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        VelocityTracker tracker = VelocityTracker.obtain();
        tracker.addMovement(event);
        tracker.computeCurrentVelocity(1000);//一個時間單元或時間間隔,單位爲毫秒
        float xVelocity = tracker.getXVelocity();
        float yVelocity = tracker.getYVelocity();
        return super.onTouchEvent(event);
    }

注:獲取速度之前必須先計算速度,即getXVelocity和getYVelocity之前必須要調用computeCurrentVelocity方法.這裏的速度是指一段時間內手指所滑過的像素數,比如將時間設置爲1000ms時,在1s內,手指在水平方向從左向右滑過100像素,那麼水平速度就是100.且速度可以爲負數,當手指從右向左滑動時,水平方向速度即爲負值.
計算公式:

速度 = (終點位置 - 起點位置) / 時間段

當不需要使用後需重置回收.

 tracker.clear();
 tracker.recycle();

GestureDetector

手勢檢測,用於輔助檢測用戶的單擊、滑動、長按、雙擊等行爲.

使用方式

創建GestureDetector對象並實現OnGestureListener接口,如果需要監聽雙擊行爲還可以實現OnDoubleTapListener接口.並接管onTouchEvent方法.

public class SeanView extends View implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {

GestureDetector detector = new GestureDetector(this);
detector.setIsLongpressEnabled(false);//解決長按屏幕後無法拖動問題
  
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean consume = detector.onTouchEvent(event);
        return consume;
    }
}
方法介紹
  • OnGestureListener
    • onDown 手指接觸屏幕的瞬間
    • onShowPress 手指接觸屏幕的瞬間,尚未鬆開或拖動
    • onSingleTapUp 單擊
    • onScroll 拖動
    • onLongPress 長按
    • onFling 快速滑動
  • OnDoubleTapListener
    • onDoubleTap 雙擊 與onSingleTapConfirmed互斥
    • onSingleTapConfirmed 單擊且後續無單擊行爲
    • onDoubleTapEvent 雙擊

Scroller

用於實現View的彈性滑動.Scroller本身無法讓View彈性滑動,它需要和computeScroll方法配合使用.

 private Scroller scroller = new Scroller(getContext());

    private void smoothScrollTo(int destX, int destY) {
        int scrollX = getScrollX();
        int delta = destX - scrollX;
        scroller.startScroll(scrollX, 0, delta, 1000);
        invalidate();
    }

    @Override
    public void computeScroll() {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.getCurrX(), scroller.getCurrY());
            postInvalidate();
        }
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章