android 事件分發複習

 

//1.事件在Activity 中的傳遞 
public boolean dispatchTouchEvent(MotionEvent ev) {
        //按下事件
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
            //空方法,當用戶點擊屏幕時會調用這個方法,可用來實現屏幕保護
        }
        
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        //如果所有的view 都不消費該事件,那麼事件最終會到達 activity 的onTouchEvent
        //相反、如果上一步getWindow().superDispatchTouchEvent(ev) 返回true 那麼不會到達
        //activity 的onTouchEvent(ev)
        return onTouchEvent(ev);
    }


  //註釋說默認實現永遠返回false
   public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }

        return false;
    }

總結:事件在activity的傳遞,事件從activity的dispatchTouchEvent開始,傳遞給getWindow().superDispatchTouchEvent(ev),如果返回false 那麼將會傳遞給自己的
onTouchEvent(默認實現返回false)

//2.事件在Window 中的傳遞 window 是抽象類,實現類phonewindow
//Activity 通過getWindow().superDispatchTouchEvent(ev),將事件傳遞給了window 對象

//window decor 的關係,activity.setContentView() 的時候會創建DecorView,並根據Theme中的//Feature 選擇contentParent 佈局,setContentView 最終是添加到contentParent 中id 爲//ID_ANDROID_CONTENT中

    @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
//將事件傳遞到DecorView 中
        return mDecor.superDispatchTouchEvent(event);
    }

//3.事件在ViewGroup中傳遞
DecorView 
  public boolean superDispatchTouchEvent(MotionEvent event) {
        //調用父類ViewGroup 的dispatchTouchEvent
        return super.dispatchTouchEvent(event);
    }

事件在ViewGroup 中傳遞的僞代碼

public boolean dispatchTouchEvent(MotionEvent ev){
    //1.決定是否由自己處理
    if(允許攔截(disallowIntercept) && onInterceptTouchEvent(ev)){
        //調用父類View 的dispatchTouchEvent 即交給自己處理
        return super.dispatchTouchEvent(ev)
    }
     // 2.通過for循環,遍歷了當前ViewGroup下的所有子View
      for(int i = 0;i<childCount;i++){
        View child = getchildAt(i);
        if(child.dispatchTouchEvent(ev)){
            return true;
        }
    }
   //3.如果沒有攔截,但是所有的子view 都不處理 和第一步一樣 同在View 的傳遞
    return super.dispatchTouchEvent(ev)
}

}


事件在View 中的傳遞僞代碼
public boolean dispatchTouchEvent(MotionEvent ev){
   //1.如果設置了ontouchlistener (mViewFlags & ENABLED_MASK) == ENABLED
    //如果mOnTouchListener.onTouch 返回true 則直接返回true 事件分發結束
    //否則 調用onTouchEvent(event)
    if(ENABLED && mOnTouchListener.onTouch(ev)){
        return true;
    }else{
        return onTouchEvent(event);
    }
}

public boolean onTouchEvent(MotionEvent event){
  //如果view 可點擊,但卻是DISABLED
    if(clickable && DISABLED){
        return true;
    }
//如果可點擊一定返回true 否則返回false
    if(clickable ){
       performClick()
       return true
    }else{
        return false
    }

}
 public boolean performClick(){
    如果設置了onclickListener 返回true
    否則返回false
}


總結:事件的整個流程
1.Activity
dispatchTouchEvent(MotionEvent ev){
 if(window.superDispatchTouchEvebt()){
    return true;
   }
//如果所有的view 都不處理,就到activity 的onTouchEvent()默認返回false
 return onTouchEvent();
}

2.ViewGroup
dispatchTouchEvent(MotionEvent ev){
    1.是否允許攔截並且攔截->把自己當成一個view ->view.dispatchTouchEvent()
    2.不攔截 遍歷子控件->child.dispatchTouchEvent() 如果子控件返回true 那麼事件傳遞結束
    3.如果不攔截、子控件也不處理->把自己當成一個view->View.dispatchTouchEvent()
}

3.View 
dispatchTouchEvent(MotionEvent ev){
  1.enabled 並且設置了 ontouchListener->listener.onTouch()
   如果ontouch 返回true ,返回true 事件分發結束
  2.如果沒設置ontouchListener 或者 前面的onTouch 返回false
   ->onTouchEvent(ev)
}

onTouchEvent(ev){
 1.如果clickable 判斷是點擊事件->performClick 返回true
 2.不可點擊 返回false 
}

performClick(){
    //設置clickListener 返回true
    //否則返回false
}

 

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