在項目中,經常遇到事件衝突,ScrollView,ViewPager滑動卡頓等情況,比如:onClick和onLongClick事件衝突,dispatchTouchEvent,onInterceptTouchEvent這些方法都有一個boolean返回值,不同返回值事件處理機制是不同的。 一:事件分 ...
在項目中,經常遇到事件衝突,ScrollView,ViewPager滑動卡頓等情況,比如:onClick和onLongClick事件衝突,dispatchTouchEvent,onInterceptTouchEvent這些方法都有一個boolean返回值,不同返回值事件處理機制是不同的。
一:事件分發流程
1:現在有一個場景,用戶長按button,我們希望只觸發onLongClick,然而onClick事件也觸發了.
這種情況比如簡單,直接在onLongClick返回true就可以解決了,返回true表示onLongClick消費了這次事件。
2:view 和 viewGroup的介紹
View是所有UI組件的基類(如:TextView,Button,ImageView),而 ViewGroup是容納這些組件的容器(如:LinearLayout,ReltiveLayout),ViewGroup是View派生出來的.
view有dispatchTouchEvent,onTouchEvent這兩個方法,ViewGroup多了一個onInterceptTouchEvent方法,此方法決定觸發事件是自己處理,還是分發給下一個組件處理.
2:事件涉及到的常用方法
用戶點擊屏幕時,將觸發viewGroup的dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);
3:方法返回值介紹
dispatchTouchEvent是處理觸摸事件分發,事件(多數情況)是從Activity的dispatchTouchEvent開始的。執行super.dispatchTouchEvent(ev),事件向下分發。
onInterceptTouchEvent是ViewGroup提供的方法,預設返回false,返回true表示攔截,返回true後,由該類的onTouchEvent方法來執行。
onTouchEvent是View中提供的方法,ViewGroup也有這個方法,view中不提供onInterceptTouchEvent。view中預設返回true,表示消費了這個事件。
二:舉一個慄子
1 老闆將一個任務分配給經理,經理將任務分配給員工去完成,員工完成後,將結果反饋給經理,經理將任務結果反饋給老闆,這是預設流程。
預設流程dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev),全部返回super.xxxxxxx
輸出日誌的結果
10-15 20:13:31.600 8716-8716/com.activity E/info: BossView dispatchTouchEvent() boss create task! 10-15 20:13:31.600 8716-8716/com.activity E/info: BossView onInterceptTouchEvent() boss將task 分配給manager 10-15 20:13:31.600 8716-8716/com.activity I/info: ManagerView 經理讓onInterceptTouchEvent決定任務由誰完成 10-15 20:13:31.600 8716-8716/com.activity I/info: ManagerView onInterceptTouchEvent()經理接收到任務,將任務分配給員工 10-15 20:13:31.601 8716-8716/com.activity I/info: EmployeesView 員工開始工作. 10-15 20:13:31.601 8716-8716/com.activity I/info: EmployeesView 員工圓滿完成任務. 10-15 20:13:31.602 8716-8716/com.activity I/info: ManagerView onTouchEvent() 經理驗收任務結果,並向老闆報告 10-15 20:13:31.602 8716-8716/com.activity E/info: BossView onTouchEvent() 工作已經完畢
2 老闆將一個任務分配給經理,經理將任務分配給員工去完成,員工覺得難度大,無法完成(onTouchEvent返回true),由於老闆沒有接收到工作報告,會不停向經理分發任務(managerView的dispatchTouchEvent方法將不停被調用,員工的dispatchTouchEvent方法也會被繼續調用)。
輸出日誌:
3 老闆將一個任務分配給經理,因為上一次任務,經理並未收到員工的工作報告,所以這次經理決定,自己的來本次完成,將事件直接消費(onInterceptTouchEvent返回true),不分給員工去做,讓員工一邊涼快去 。
日誌輸出:
10-15 22:11:26.877 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_DOWN 10-15 22:11:26.878 22219-22219/com.activity E/info: BossView dispatchTouchEvent() boss create task! 10-15 22:11:26.879 22219-22219/com.activity E/info: BossView onInterceptTouchEvent() boss將task 分配給manager 10-15 22:11:26.879 22219-22219/com.activity I/info: ManagerView 經理讓onInterceptTouchEvent決定任務由誰完成 10-15 22:11:26.879 22219-22219/com.activity I/info: ManagerView onInterceptTouchEvent()經理接收到任務安排,員工做得不好,自己來做任務 10-15 22:11:26.879 22219-22219/com.activity I/info: ManagerView onTouchEvent() 經理驗收任務結果,並向老闆報告 10-15 22:11:26.879 22219-22219/com.activity E/info: BossView onTouchEvent() 工作已經完畢 10-15 22:11:26.886 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE 10-15 22:11:26.902 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE 10-15 22:11:26.912 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE 10-15 22:11:26.919 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_MOVE 10-15 22:11:26.921 22219-22219/com.activity I/info: MainActivity--dispatchTouchEvent()ACTION_UP
三:代碼
由於代碼差不多,這裡只貼出ManagerView的代碼,完整代碼下載連接在文章下方
public class ManagerView extends LinearLayout {
private final String TAG="ManagerView ";
private int index=0;
public ManagerView(Context context) {
super(context);
}
public ManagerView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(index==0){
Log.i("info",TAG+" onTouchEvent() 經理驗收任務結果,並向老闆報告");
}else{
Log.i("info",TAG+" onTouchEvent() 自己親自來完成任務");
}
return super.onTouchEvent(event);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
index = 0;
// if(index==0){
// Log.i("info",TAG+"onInterceptTouchEvent()經理接收到任務,將任務分配給員工");
// return super.onInterceptTouchEvent(ev);
// }else{
Log.i("info",TAG+"onInterceptTouchEvent()經理接收到任務安排,員工做得不好,自己來做任務");
return true;
// }
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i("info",TAG+"經理讓onInterceptTouchEvent決定任務由誰完成");
return super.dispatchTouchEvent(ev);
}
}
備註:上傳代碼時,我電腦github出了點小問題,如果代碼有問題,請留言,代碼下載地址:github