上面这张图描述的是事件的传递,当我们点击button的时候事件上事件的传递是先走的RelativeLayout的触摸事件,之后传递给Button,在Button没有消耗的情况下,还会传递给上一层。 下面上代码验证一下:布局就是一个自定义的相对布局relative里面放置一个自定义的Button,并重写里面的 代码如下:
@SuppressLint("AppCompatCustomView")
public class MyButton extends Button {
private static final String TAG = "lang";
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i(TAG,"Button dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
}
因为代码重复,直上一个的代码,运行之后我们查看打印的结果。
这里的dispatchTouchEvent方法就是做事件分发用的,好的我们先岔开话题,讨论一下,View的OnTouch事件和OnClick事件的关系,代码的写法布局上是一样的,不多说先上代码:
Button button = (Button) findViewById(R.id.btn);
button.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
Log.i(TAG,"Button onTouch"+motionEvent.getAction());
return true;
}
});
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.i(TAG,"Button OnClick");
}
});
运行打印看效果: 首先运行的事OnTouch事件,之后才走的OnClick事件,当我们OnTouch返回true的时候,运行看效果:我们发现OnClick事件没有响应,原因是没有接收到UP事件。所以我们可以得到以下的结论:1.控件的Listener事件触发的顺序是先onTouch,再onClick。
2.控件的onTouch返回true,将会onClick事件没有了---阻止了事件的传递。
返回false,才会传递onClick事件(才会传递up事件)下面我们来讨论,View本身的onTouch事件和Listener事件还有dispatchTouchEvent事件之间的关系:
先贯穿以下顺序,不多说先上代码首先是设置一个touch监听,之后再View中:@SuppressLint("AppCompatCustomView")
public class MyButton extends Button {
private static final String TAG = "lang";
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i(TAG,"Button dispatchTouchEvent");
return super.dispatchTouchEvent(event);
// return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG,"Button onTouchEvent");
return super.onTouchEvent(event);
}
}
打印验证事件传递的顺序:这个是走的顺序,当我们在
这里只返回true的时候,我们运行的效果是也就是是说事件会在这里终止,但是,当我们这样的时候:效果:所以super.dispatchTouchEvent是实际的分发代码,同理,我们的OnTouch也是如此,这里我们就不验证了。但是我们在Listener事件里面返回true的时候呢?当:运行的效果是这样的:所以我们可以得到这样的结论:
1.如果onTouchListener的onTouch方法返回了true,那么view里面的onTouchEvent就不会被调用了。顺序dispatchTouchEvent-->onTouchListener---return false-->onTouchEvent
2.如果view为disenable,则:onTouchListener里面不会执行,但是会执行onTouchEvent(event)方法
3.onTouchEvent方法中的ACTION_UP分支中触发onclick事件监听
onTouchListener-->onTouch方法返回true,消耗次事件。down,但是up事件是无法到达onClickListener.
onTouchListener-->onTouch方法返回false,不会消耗此事件
后两条结论是通过分析源码所得来的:这里就不分析源码了,可以自己去验证,希望对小伙伴们有帮助。有错的地方可以留言指正。谢谢