關(guān)于android事件分發(fā)和手勢監(jiān)聽的整理

Android View的onTouchEvent和OnTouch區(qū)別

1.通過重寫onTouchEvent方法來處理諸如MotionEvent.ACTION_DOWN、MotionEvent.ACTION_MOVE/MotionEvent.ACTION_UP的消息:

public class MyTextView extends TextView{

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean value = super.onTouchEvent(event);
        System.out.println("super.onTouchEvent: " + value+ " event: " + event.getAction());
        return value;
    }
}

2.通過實現(xiàn)OnTouchListener的接口,實現(xiàn)onTouch回調(diào):

class MyTouchListener implements View.OnTouchListener{  
    @Override  
    public boolean onTouch(View v, MotionEvent event) {  
                        float x = event.getX();
                float y = event.getY();
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:                        
                        break;
                    case MotionEvent.ACTION_MOVE:                        
                        break;
                    case MotionEvent.ACTION_UP:
                        break;
                    default:
                        break;
                }
                return true; //這里返回false的話 無法響應(yīng)MOVE和UP。
    }  
}  
我在之前做的播放器的手勢控制音量、亮度和快進(jìn)回退就是通過這個來控制的,簡單粗暴。

3.倆者區(qū)別:

public boolean dispatchTouchEvent(MotionEvent event){  
    ... ...  
    if(onFilterTouchEventForSecurity(event)){  
        ListenerInfo li = mListenerInfo;  
        if(li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED  
            && li.mOnTouchListener.onTouch(this, event)) {  
            return true;  
        }  
        if(onTouchEvent(event)){  
            return true;  
        }  
    }  
    ... ...  
    return false;  
}  

onTouchListener的接口的優(yōu)先級是要高于onTouchEvent的,假若onTouchListener中的onTouch方法返回true,表示此次事件已經(jīng)被消費了,那onTouchEvent是接收不到消息的。
onTouchListener的onTouch方法優(yōu)先級比onTouchEvent高,會先觸發(fā)。
假如onTouch方法返回false會接著觸發(fā)onTouchEvent,反之onTouchEvent方法不會被調(diào)用。
類似onclick的事件是基于onTouchEvent實現(xiàn),在onTouch中,如果返回false,則可以響應(yīng)到onTouchEvent,但是無法響應(yīng)到onTouch手勢中的move和up事件。
該小結(jié)參考:http://blog.csdn.net/huiguixian/article/details/22193977

GestureDetector類及其用法

View類有個View.OnTouchListener內(nèi)部接口,通過重寫他的onTouch(View v, MotionEvent event)方法,我們可以處理一些touch事件,但是這個方法太過簡單,如果需要處理一些復(fù)雜的手勢,用這個接口就會很麻煩(因為我們要自己根據(jù)用戶觸摸的軌跡去判斷是什么手勢)。

@Override
public boolean onTouch(View v, MotionEvent event) {
    return mGestureDetector.onTouchEvent(event);
}

GestureDetector這個類對外提供了兩個接口:OnGestureListener,OnDoubleTapListener(雙擊),還有一個內(nèi)部類SimpleOnGestureListener。

使用方法
  1. 實現(xiàn)內(nèi)部方法
  • 內(nèi)部類
class MyGestureListener implements GestureDetector.OnGestureListener {

        @Override
        public boolean onDown(MotionEvent e) {
            return false;
        }

        @Override
        public void onShowPress(MotionEvent e) {

        }

        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
            return false;
        }

        @Override
        public void onLongPress(MotionEvent e) {

        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return false;
        }
    }
  • 匿名內(nèi)部類
mGestureDetector = new GestureDetector(mContext, new GestureDetector.OnGestureListener() {
            @Override
            public boolean onDown(MotionEvent e) {
                return false;
            }

            @Override
            public void onShowPress(MotionEvent e) {

            }

            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                return false;
            }

            @Override
            public void onLongPress(MotionEvent e) {

            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                return false;
            }
        });
  1. 創(chuàng)建GestureDetector實例

過時

public GestureDetector(OnGestureListener listener, Handler handler) {
        this(null, listener, handler);
}

過時

public GestureDetector(OnGestureListener listener) {
        this(null, listener, null);
}
public GestureDetector(Context context, OnGestureListener listener) {
        this(context, listener, null);
}
public GestureDetector(Context context, OnGestureListener listener, Handler handler)
public GestureDetector(Context context, OnGestureListener listener, Handler handler,
            boolean unused) {
        this(context, listener, handler);
  }

匿名內(nèi)部類
mGestureDetector = new GestureDetector(mContext,new MyGestureListener());

  1. 實現(xiàn)View.OnTouchListener接口,重寫OnTouch()方法

參照上一段

  1. 在onTouch()方法中攔截事件處理,將控制權(quán)交給GestureDector。
@Override
public boolean onTouch(View v, MotionEvent event) {
        return mGestureDetector.onTouchEvent(event);
}
  1. View.setOnTouchListener()

super.setOnTouchListener(this);
mGestureDetector.setOnDoubleTapListener(new MyGestureListener());

SimpleOnGestureListener

SimpleOnGestureListener是GestureDetector類的一個內(nèi)部類,該類是static class,也就是說它實際上是一個外部類。可以在外部繼承這個類,重寫里面的具體某些手勢處理方法。

class MyOnGestureListener extends SimpleOnGestureListener{
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return super.onFling(e1, e2, velocityX, velocityY);
        }
}

android給我們封裝提供了常用的類,比如雙擊監(jiān)聽android給我們提供OnDoubleTapListener,比如滑動或者按下再抬起的操作,這個android也幫我封裝了好了,實現(xiàn)這個接口SimpleOnGestureListener就行,這個SimpleOnGestureListener類是實現(xiàn)了OnGestureListener,由于這個接口方法過多,所以使用了類SimpleOnGestureListener去實現(xiàn)OnGestureListener接口,你想覆蓋什么方法就重寫就行。
該小結(jié)參考:http://blog.csdn.net/hpk1994/article/details/51224228
http://www.cnblogs.com/rayray/p/3422734.html

事件分發(fā)

  • dispatchTouchEvent
    只要你觸摸到了任何一個控件,就一定會調(diào)用該控件的dispatchTouchEvent方法,該方法在View和ViewGroup中。比如你點擊button就是button->textView->View。
public boolean dispatchTouchEvent(MotionEvent event) {  
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
        mOnTouchListener.onTouch(this, event)) {  
        return true;  
    }  
    return onTouchEvent(event);  
}  

根據(jù)代碼可以看出,首先判斷dispatchevent中ontouchlistener是否有值而且要判斷該view是否為enable,第三個條件則是onTouch這個回調(diào)的返回值是否為true,也就是說onTouch為true則dispatchevent根據(jù)前兩個條件直接返回true,否則返回false繼續(xù)向下執(zhí)行,也就意味著后面的onTouchEvent和onclick不會執(zhí)行。
為默認(rèn)在onTouchEvent返回true所以不管ontouch返回的是什么,action_move,action_up都會執(zhí)行。而textview中ontouch不會返true則不會執(zhí)行action_move,action_up。

  • onInterceptTouchEvent
    當(dāng)你點擊一個layout中的button時,首先點擊的而是最外層layout,所以調(diào)用的是最外層viewGroup的dispatchtouchevent。
    而在viewgourp的dispatchtouchevent中有onintercepttouchevent方法默認(rèn)為false,如果這個方法返回true則示為事件攔截,則直接執(zhí)行viewgroup的dispatchevent,否則進(jìn)入下層遍歷所有子view,尋找點擊的子view。
    如果父view和子view都有事件消耗,則由于事件傳遞優(yōu)先是子view消耗,然后返回true。
  • onTouchEvent
    onTouchEvent中MotionEvent.ACTION_UP中performclick中實現(xiàn)了onclick,且返回true。
    即dispatchEvent->(onInterceptTouchEvent->dispatchEvent->)onTouch->onTouchEvent->onClick
    viewGroup沒有onTouchListener,在viewGroup中dispatchEvent中會有調(diào)用view.dispatchEvent,這個代碼同樣在interceptTouchEvent后面。
    該小結(jié)參考:http://blog.csdn.net/guolin_blog/article/details/9097463/
    http://blog.csdn.net/guolin_blog/article/details/9153747

getX,getRawX,getWidth,getTranslationX

getLeft、getRight、getTop、getButton分別是四個方向距離父view左側(cè)和上側(cè)的距離。
而getX、getRaw是onTouch里面的方法,分別代表的是觸摸點到自身的距離和觸摸點到屏幕的距離,這個很好理解。
getX和getLeft都是獲取View相對父View左側(cè)的坐標(biāo),但是通過屬性動畫可以改變view的屬性,即x和translateX的值,但是left值不變,所以屬性動畫執(zhí)行后的結(jié)果是x = translationX + left。

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

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

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