View的事件體系(一)

View的基本知識

View的位置參數(shù):有四個屬性,top,left,right,bottom。top是左上角的縱坐標(biāo),left是左上角的橫坐標(biāo),bottom是右下角的縱坐標(biāo),right是右下角的橫坐標(biāo)。由此可得:

width = right - left
heightj = bottom - top

這四個屬性的獲取方式:
Left = getLeft();
Right = getRight();
Top = getTop();
Bottom = getBottom();

在Android3.0后,View增加了額外的參數(shù):x,y,translationX和translationY,其中x,y是View左上角的左邊,translationX和translationY是View左上角相對于父容器的偏移量。translationX,translationY的默認(rèn)值為0.
需要注意的是,View在平移過程中,top,left表示的是原始左上角的位置信息,其值并不會改變,此時(shí)改變的是x,y,translationX和translationY這四個參數(shù)。所以:

x = left + translationX
y = top + translationY

MotionEvent

可以通過MotionEvent對象得到點(diǎn)擊事件發(fā)送的x和y坐標(biāo)。為此,系統(tǒng)提供了兩組方法:getX/getY和getRawX/getRawY。getX/getY返回的是相當(dāng)于當(dāng)前View左上角的x和y坐標(biāo),而getRawX和getRawY獲得是相當(dāng)于手機(jī)屏幕左上角的x和y坐標(biāo)。

TouchSlop

TouchSlop是系統(tǒng)所能識別的被認(rèn)為是滑動的最小距離??梢酝ㄟ^ViewConfiguration.get(getContext ()).getScaledTouchSlop()方法來獲取這個常量。

VelocityTracker 速度追蹤

速度追蹤,用于追蹤手指在滑動過程中的速度,包括水平速度和豎直方向速度。他的用法很簡單就,首先,在View的onTouchEvent方法中追蹤當(dāng)前點(diǎn)擊事件的速度:

VelocityTracker velocityTracker = VelocityTracker.obtain();
velocityTracker.addMovement(event);

接著,通過如下方式來獲得當(dāng)前的速度:

velocityTracker.computeCurrentVelocity(1000);       //先計(jì)算移動速度,1000代表在1000ms中,移動的像素
Int xVelocity = (int) velocityTracker.getXVelocity() ;   //獲取剛剛計(jì)算出的1000ms中x軸方向移動的像素
int yVelocity = (int) velocityTracker.getYVelocity();     //獲得剛剛計(jì)算出的1000ms中y軸方向移動的像素

最后當(dāng)不需要使用它的時(shí)候,需要調(diào)用clear方法來重置并回收內(nèi)存

velocityTracker.clear();
velocityTracker.recycle();

GestureDetector

  • 第一步:Activity或者View在面對觸摸事件時(shí),可以重寫他們的默寫方法來自定義他們對面觸摸事件的反應(yīng)。對于Activity而言,我們可以直接重寫onTouchEvent()方法
public class MainActivity extends Activity {
...
// This example shows an Activity, but you would use the same approach if
// you were subclassing a View.
@Override
public boolean onTouchEvent(MotionEvent event){ 
        //對event的處理
        return true;
}

對于View而言,我們可以通過View.onTouchListener接口,重寫他的onTouch方法來自定義觸摸事件的處理方式

View myView = findViewById(R.id.my_view); 
myView.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        // ... Respond to touch events       
        return true;
    }
});
  • 第二步,在重寫onTouch方法或者onTouchEvent方法時(shí),我們可以通過GestureDetector類來幫助我們檢測用戶的單擊,滑動,長按,雙擊等行為。在定義GestureDetector中,重寫其中各個方法中,加入我們需要進(jìn)行的操作。
    下面的是Activity的例子
public class MainActivity extends Activity implements 
        GestureDetector.OnGestureListener,                           //實(shí)現(xiàn)了OnGestureListener接口
        GestureDetector.OnDoubleTapListener{                          //實(shí)現(xiàn)了雙擊判斷接口
    
    private static final String DEBUG_TAG = "Gestures";
    private GestureDetectorCompat mDetector; 

    // Called when the activity is first created. 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Instantiate the gesture detector with the
        // application context and an implementation of
        // GestureDetector.OnGestureListener
        mDetector = new GestureDetectorCompat(this,this);
        // Set the gesture detector as the double tap
        // listener.
        mDetector.setOnDoubleTapListener(this);
    }

    @Override 
    public boolean onTouchEvent(MotionEvent event){ 
        this.mDetector.onTouchEvent(event);
        // Be sure to call the superclass implementation
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent event) { 
        Log.d(DEBUG_TAG,"onDown: " + event.toString());         //加入我們需要的操作
        return true;
    }

    @Override
    public boolean onFling(MotionEvent event1, MotionEvent event2, 
            float velocityX, float velocityY) {
        Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());  //加入我們需要的操作
        return true;
    }

    @Override
    public void onLongPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onLongPress: " + event.toString());     //加入我們需要的操作
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString());     //加入我們需要的操作
        return true;
    }

    @Override
    public void onShowPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onShowPress: " + event.toString());      //加入我們需要的操作
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());    //加入我們需要的操作
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent event) {
        Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());     //加入我們需要的操作
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent event) {
        Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString());    //加入我們需要的操作
        return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());    //加入我們需要的操作
        return true;
    }
}

在View中,使用方法如下:在此之前,要定義并初始化mDetector。

 View myView = findViewById(R.id.my_view); 
        myView.setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                // ... Respond to touch events       
                this.mDetector.onTouchEvent(event);
                return super.onTouchEvent(event);
            }
        });
  • 如果你只想實(shí)現(xiàn)一部分GestureDetector.OnGestureLisner接口中的方法,你可以繼承GestureDetector.SimpleOnGestureListener類。這個類實(shí)現(xiàn)了GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, 和 GestureDetector.OnContextClickListener 接口中的所有的方法,但是在實(shí)現(xiàn)了沒有做任何事情,僅僅是return false;。
public class MainActivity extends Activity { 
    
    private GestureDetectorCompat mDetector; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDetector = new GestureDetectorCompat(this, new MyGestureListener());
    }

    @Override 
    public boolean onTouchEvent(MotionEvent event){ 
        this.mDetector.onTouchEvent(event);
        return super.onTouchEvent(event);
    }
    
    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        private static final String DEBUG_TAG = "Gestures"; 
        
        @Override
        public boolean onDown(MotionEvent event) { 
            Log.d(DEBUG_TAG,"onDown: " + event.toString()); 
            return true;
        }

        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2, 
                float velocityX, float velocityY) {
            Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString());
            return true;
        }
    }
}

不管你是實(shí)現(xiàn)GestureDector.OnGestureListener接口還是繼承GestureDector.SimpleOnGestureListener類,最好都實(shí)現(xiàn)其中的onDown( )方法,即在里面renturn true;。 因?yàn)樗械氖謩荻际?code>onDown()方法開始的,如果你返回了false(正如GestureDector.SimpleOnGestureListener類中默認(rèn)實(shí)現(xiàn)法的), 系統(tǒng)就會認(rèn)為你打算忽略后面所有的手勢,其后面所有的手勢判斷方法都不會執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容