Android 事件分发介绍

来源:互联网 发布:北京python工程师工资 编辑:程序博客网 时间:2024/05/20 09:05

事件分发所解决的问题:

onTouch和onTouchEvent有什么区别,又该如何使用?

为什么给ListView引入了一个滑动菜单的功能,ListView就不能滚动了?

ListView的Item中有Button,onItemClick为什么会失效?

等。。。

什么是事件分发:

事件分发就是当用户点击了屏幕,那么就触发了一个事件event,而这个事件在每一层的传递与分发过程就叫做事件分发。

三个主要的方法:

dispatchTouchEvent接收事件、onTouchEvent消费事件 (这两个方法存在view中);

onInterceptTouchEvent截断事件交给onTouchEvent处理掉(这个方法存在viewGroup)。

分发过程:

只要你触摸到了一个控件,那么事件主要按照activity→viewgroup→view的顺序传递,

(这里并不是准确的顺序,所谓主要就是我们一般只会在这三个层面对事件分发过程进行介入与及操作)

首先在activity中执行dispatchTouchEvent接收事件,activity不存在onInterceptTouchEvent方法,

所以不能截断事件,当然也不能执行截断事件后的onTouchEvent,这时候activity就把事件传递给了

viewgroup的dispatchTouchEvent,viewgroup默认onInterceptTouchEvent为false即不拦截,直接把

事件传递给了view的dispatchTouchEvent,view接收到这个事件因为没onInterceptTouchEvent不能

截断并且处于最下层已经不能再往下传了,所以只能执行onTouchEvent消费了这个事件,但是在这之前

他会判断这个view是否符合三个条件:

1,控件注册了setOnTouchListener事件

2,控件的enabletrue

3onTouch方法里返回true

满足以上三个条件执行完onTouchdispatchTouchEvent方法返回true,传递结束,否则返回false,事件传递给控件的onclick和onTouchEventTextViewclick默认返回为falseButton,checkBox默认返回为true

onTouchEvent返回为false的话则把事件传递给与其父view的onTouch,以此类推

结论:

(所以以上流程任一项返回了true,则事件终止传递,自定义一个layout重写以上任意方法返回true亦会终止。)

下面是一个activity复写dispatchTouchEvent方法拦截点击事件,隐藏输入法的例子:

//这个方法判断是否点击了editText外部

public static boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] leftTop = { 0, 0 };
v.getLocationInWindow(leftTop);
int left = leftTop[0], top = leftTop[1], bottom = top
+ v.getHeight(), right = left + v.getWidth();
if (event.getX() > left && event.getX() < right  
&& event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}

//这个方法用于隐藏输入法
public static Boolean hideInputMethod(Context context, View v) {
InputMethodManager imm = (InputMethodManager) context
.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm != null) {
return imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
return false;
}


 @Override
   public boolean dispatchTouchEvent(MotionEvent ev) {
       if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
           View v = getCurrentFocus();
           if (HideInput.isShouldHideInput(v, ev)) {
               if(HideInput.hideInputMethod(this, v)) {
                   return true; //返回true,拦截事件,其他控件不响应,注释则不拦截点击事件。
               }
           }
       }
       return super.dispatchTouchEvent(ev);   
   }




0 0
原创粉丝点击