Android View事件傳面試相關

View 事件分發

  • 傳遞圖示

  • 事件攔截的應用場景
  • 面試題
    • 爲什麼要有事件傳遞機制
      • 因爲android的view 是樹形結構,當點擊事件發生的時候 要經過好幾層的View ,若是沒有事件傳遞機制 ,就沒辦法確定這個事件給誰處理了,所以事件傳遞機制就是爲了處理這個問題而出現的
    • android佈局加載的過程
      • 用戶執行Activity的setContentView方法,內部是PhoneWindow的setContentView方法,在PhoneWindow中完成DecorView的創建,
      • PhoneWindow是window的實現類.
      • DecorView是Activity的根View,也是PhotoWindow的內部類,並且繼承了Framlayout.
      • DecorView將屏幕分爲2個部分:titleView和contentView,我們平常加載的佈局就是ContentView.
    • android 事件傳遞的三個重要方法

      • viewgroup 擁有這三個方法 acitivity和view沒有攔截方法,

    • 事件分發的流程
      • Activity——>PhoneWindow——>DecorView——>ViewGroup——>...——>View

    • onTouchListener,onTouchEvent和onClick的優先級別
      • onTouchListener—–>onTouchEvent—>onclick
      • onTouchListener >>> onTouchEvent >>> setOnLongClickListener >>> OnClickListerner
      • 總結
        • onTouch的優先級高於onClick
        • 控件被點擊時,onTouch返回false—>dispatchTouchEvent方法返回false—>執行onTouchEvent—>在performClick方法裏回調onClick
        • onTouch返回true—>dispatchTouchEvent方法返回true—>不執行onTouchEvent,顯然onClick方法也不會被調用
        • 參考https://juejin.im/entry/58df5b33570c35005798493c
      • 面試口述
        • onTouchListener 的優先級要高於onTouchEvent ,若onTouchListener返回的是true onTouchEvent 就不執行了
    • View中爲什麼沒有onInterceptTouchEvent事件攔截方法?
      • View最爲事件傳遞的最末端,要麼消費掉事件,要麼不處理進行回傳,根本沒必要進行事件攔截
    • 用僞代碼表示ViewGroup的事件分發過程並解釋?

      • 對於一個ViewGroup來說,點擊事件產生後,首先會傳遞給它,這時她的dispatchTouchEvent會被調用,如果這個ViewGroup的onInterceptTouchEvent,方法返回true表示它要攔截當前事件,接着事件就會交給這個ViewGroup處理,即它的onTouchEvent就會被調用;如果這個這個ViewGroup的onInterceptTouchEvent,方法返回false就表示它不攔截當前事件,這時事件就會傳遞給子元素,接着子元素的dispatchTouchEvent方法就會被調用,如此反覆直到事件最終被處理。
    • 常見的注意問題
      • 如果事件一直沒有被消費,最後會傳給Activity,如果Activity也不需要就被拋棄。
      • view事件執行順序dispatchTouchEvent-> setOnTouchListener的onTouch->onTouchEvent,如果setOnTouchListener返回ture,後續事件onTouchEvent不在執行
      • onClick是在onTouchEvent(event)方法中的,所以onTouch優先於onClick執行
      • 如果重寫dispatchTouchEvent方法,dispatchTouchEvent無論返回true還是false,事件都不再進行分發, 只有當其返回super.dispatchTouchEvent(ev),才表明其具有向下層分發的願望。
    • setOnLongClickListener的onLongClick的返回值表示什麼?
      • 返回false,長按的話會同時執行onLongClick和onClick;如果setOnLongClickListener返回true,表示事件被消耗,不會繼續傳遞,只執行longClick;
    • requestDisallowInterceptTouchEvent 可以在子元素中干擾父元素的事件分發嗎?如果可以,是全部都可以干擾嗎?
      • 答:肯定可以,但是down事件干擾不了。
  • 簡述事件傳遞的流程
    • 事件都是從Activity.dispatchTouchEvent()開始傳遞
    • 一個事件發生後,首先傳遞給Activity,然後一層一層往下傳,從上往下調用dispatchTouchEvent方法傳遞事件:
    • activity --> ~~ --> ViewGroup --> View
    • 如果事件傳遞給最下層的View還沒有被消費,就會按照反方向回傳給Activity,從下往上調用onTouchEvent方法,最後會到Activity的onTouchEvent()函數,如果Activity也沒有消費處理事件,這個事件就會被拋棄:
    • View --> ViewGroup --> ~~ --> Activity
    • dispatchTouchEvent方法用於事件的分發,Android中所有的事件都必須經過這個方法的分發,然後決定是自身消費當前事件還是繼續往下分發給子控件處理。返回true表示不繼續分發,事件沒有被消費。返回false則繼續往下分發,如果是ViewGroup則分發給onInterceptTouchEvent進行判斷是否攔截該事件。
    • onTouchEvent方法用於事件的處理,返回true表示消費處理當前事件,返回false則不處理,交給子控件進行繼續分發。
    • onInterceptTouchEvent是ViewGroup中才有的方法,View中沒有,它的作用是負責事件的攔截,返回true的時候表示攔截當前事件,不繼續往下分發,交給自身的onTouchEvent進行處理。返回false則不攔截,繼續往下傳。這是ViewGroup特有的方法,因爲ViewGroup中可能還有子View,而在Android中View中是不能再包含子View的
    • 上層View既可以直接攔截該事件,自己處理,也可以先詢問(分發給)子View,如果子View需要就交給子View處理,如果子View不需要還能繼續交給上層View處理。既保證了事件的有序性,又非常的靈活。
    • 事件由父View傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()方法對事件攔截,停止其向子view傳遞
    • 如果View沒有對ACTION_DOWN進行消費,之後的其他事件不會傳遞過來,也就是說ACTION_DOWN必須返回true,之後的事件纔會傳遞進來
  • 應用場景
    • 常見的滑動衝突
      • 外部滑動方向和內部滑動方向不一致的場景
        • ViewPager和Fragment配合使用組成的頁面滑動效果。這種衝突的解決方式,一般都是根據水平滑動還是豎直滑動(滑動的距離差)來判斷到底是由誰來攔截事件
      • 外部滑動方向和內部滑動方向一致的場景
        • 內外兩層同時能上下滑動或者能同時左右滑動。這種一般都是根據業務來進行區分。例如 ScrollView 和ListView 滑動的場景
    • 滑動事件衝突解決方案
      • 內部攔截法
      • 外部攔截法
  • 面試視角
  • 參考
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章