事件分发的小案例
mRV.setOnTouchListener((v, event) -> {
Log.e("试图传递","布局 onTouch");
return false;
});
mRV.setOnClickListener(v -> Log.e("试图传递","布局 OnClick"));
mBtn.setOnTouchListener((v, event) -> {
Log.e("试图传递","按钮 onTouch");
return false;
});
mBtn.setOnClickListener(v -> Log.e("试图传递","按钮 OnClick"));
MyDvRelativeLayout.xml
public class MyDvRelativeLayout extends RelativeLayout {
public MyDvRelativeLayout(Context context) {
super(context);
}
public MyDvRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyDvRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("事件分发","父ViewGroup dispatchTouchEvent");
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e("事件分发","父ViewGroup onInterceptTouchEvent "+super.onInterceptTouchEvent(ev));
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("事件分发","父ViewGroup onTouchEvent");
return super.onTouchEvent(event);
}
}
MyButton.xml
public class MyButton extends android.support.v7.widget.AppCompatButton {
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.e("事件分发","子View dispatchTouchEvent");
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("事件分发","子View onTouchEvent 返回: "+super.onTouchEvent(event) +" 触摸状态 "+event.getAction() );
return super.onTouchEvent(event);
}
}
点击按钮运行结果:
如下图可以发现:布局并未响应点击事件,事件的流向打印如下:
07-19 14:01:54.354 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:01:54.354 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent false
07-19 14:01:54.354 15257-15257/com.example.mydairytestproject E/事件分发: 子View dispatchTouchEvent
07-19 14:01:54.356 15257-15257/com.example.mydairytestproject E/事件分发: 子View onTouchEvent 返回: true 触摸状态 0
07-19 14:01:54.426 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:01:54.426 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent false
07-19 14:01:54.426 15257-15257/com.example.mydairytestproject E/事件分发: 子View dispatchTouchEvent
07-19 14:01:54.427 15257-15257/com.example.mydairytestproject E/事件分发: 子View onTouchEvent 返回: true 触摸状态 1
按钮的响应如下,只触发了按钮的事件,正如上图所示,由于子view的onTouchEvent( )返回了true了,那么就意味着触摸事件已经被消费了,那么就不会返回给父控件再进行处理了
07-19 14:04:04.141 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 onTouch
07-19 14:04:04.199 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 onTouch
07-19 14:04:04.200 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 OnClick
07-19 14:04:04.201 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 OnClick
合起来如下:
07-19 14:06:49.395 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:06:49.395 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent false
07-19 14:06:49.395 15257-15257/com.example.mydairytestproject E/事件分发: 子View dispatchTouchEvent
07-19 14:06:49.395 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 onTouch
07-19 14:06:49.397 15257-15257/com.example.mydairytestproject E/事件分发: 子View onTouchEvent 返回: true 触摸状态 0
07-19 14:06:49.434 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:06:49.434 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent false
07-19 14:06:49.434 15257-15257/com.example.mydairytestproject E/事件分发: 子View dispatchTouchEvent
07-19 14:06:49.434 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 onTouch
07-19 14:06:49.434 15257-15257/com.example.mydairytestproject E/事件分发: 子View onTouchEvent 返回: true 触摸状态 2
07-19 14:06:49.483 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:06:49.483 15257-15257/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent false
07-19 14:06:49.483 15257-15257/com.example.mydairytestproject E/事件分发: 子View dispatchTouchEvent
07-19 14:06:49.483 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 onTouch
07-19 14:06:49.484 15257-15257/com.example.mydairytestproject E/事件分发: 子View onTouchEvent 返回: true 触摸状态 1
07-19 14:06:49.484 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 OnClick
07-19 14:06:49.487 15257-15257/com.example.mydairytestproject E/试图传递: 按钮 OnClick
当MyButton的 onTouchEvent()如下返回false时,打印日志如下
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("事件分发","子View onTouchEvent 返回: "+super.onTouchEvent(event) +" 触摸状态 "+event.getAction() );
return false;
}
07-19 14:12:26.425 18319-18319/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:12:26.425 18319-18319/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent false
07-19 14:12:26.425 18319-18319/com.example.mydairytestproject E/事件分发: 子View dispatchTouchEvent
07-19 14:12:26.426 18319-18319/com.example.mydairytestproject E/试图传递: 按钮 onTouch
07-19 14:12:26.427 18319-18319/com.example.mydairytestproject E/事件分发: 子View onTouchEvent 返回: true 触摸状态 0
07-19 14:12:26.427 18319-18319/com.example.mydairytestproject E/试图传递: 布局 onTouch
07-19 14:12:26.427 18319-18319/com.example.mydairytestproject E/事件分发: 父ViewGroup onTouchEvent
07-19 14:12:26.496 18319-18319/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:12:26.496 18319-18319/com.example.mydairytestproject E/试图传递: 布局 onTouch
07-19 14:12:26.496 18319-18319/com.example.mydairytestproject E/事件分发: 父ViewGroup onTouchEvent
07-19 14:12:26.497 18319-18319/com.example.mydairytestproject E/试图传递: 布局 OnClick
onTouchEvent()小结
点击事件是在手指抬起时触发的,只有OnTouchEvent()默认一般情况下是返回true的,意味着事件被该控件(布局)给消费了,如果返回 false 那么意味着无法消费,那么就不得不交给父布局处理。
接下啦来把父视图的 onInterceptTouchEvent( )返回 true,即拦截事件看看,Button啥都没调用
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;
}
07-19 14:25:00.493 21372-21372/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:25:00.493 21372-21372/com.example.mydairytestproject E/事件分发: 父ViewGroup onInterceptTouchEvent true
07-19 14:25:00.493 21372-21372/com.example.mydairytestproject E/试图传递: 布局 onTouch
07-19 14:25:00.493 21372-21372/com.example.mydairytestproject E/事件分发: 父ViewGroup onTouchEvent
07-19 14:25:00.563 21372-21372/com.example.mydairytestproject E/事件分发: 父ViewGroup dispatchTouchEvent
07-19 14:25:00.564 21372-21372/com.example.mydairytestproject E/试图传递: 布局 onTouch
07-19 14:25:00.564 21372-21372/com.example.mydairytestproject E/事件分发: 父ViewGroup onTouchEvent
07-19 14:25:00.565 21372-21372/com.example.mydairytestproject E/试图传递: 布局 OnClick