自定义关键事件的传递(一)
在自定义空间中事件的传递十分重要,为了记录和巩固知识特此记录, 由于水平有限,不对的地方希望可以给小弟指正。
不废话,先上张图
上面这张图描述的是事件的传递,当我们点击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,不会消耗此事件
后两条结论是通过分析源码所得来的:这里就不分析源码了,可以自己去验证,希望对小伙伴们有帮助。有错的地方可以留言指正。谢谢