在Android触摸屏的过程中,有三个重要的方法,dispatchTouchEvent(事件分发)、onInterceptTouchEvent(事件拦截)、onTouchEvent(事件处理、消费)。
View、ViewGroup、Activity中都有dispatchTouchEvent,onTouchEvent方法;但是onInterceptTouchEvent只有ViewGroup中有。
触摸事件处理的原理请看http://blog.csdn.net/xyz_lmn/article/details/12517911,图文的方式讲解的很清楚。
我在此只是记录下,用代码进行的验证过程以及一些要点。
代码如下:
public class MyRelativeLayout extends RelativeLayout {
public MyRelativeLayout(Context context) {
super(context);
}
public MyRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.e("Demo", "RelativeLayout --> onTouchEvent"+event.getAction());
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.e("Demo", "RelativeLayout --> dispatchTouchEvent"+ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
}
public class MyButton extends Button {
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//触摸
Log.e("Demo", "Button --> onTouchEvent" + event.getAction() + "");
return super.onTouchEvent(event);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
//事件分发
Log.e("Demo", "Button --> dispatchTouchEvent" + event.getAction() + "");
return super.dispatchTouchEvent(event);
}
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener, View.OnTouchListener {
private RelativeLayout m_rlayout;
private MyButton m_button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
m_rlayout = (RelativeLayout) findViewById(R.id.relative_layout);
m_button = (MyButton) findViewById(R.id.button);
m_rlayout.setOnTouchListener(this);
m_button.setOnTouchListener(this);
m_button.setOnClickListener(this);
m_rlayout.setOnClickListener(this);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}
@Override
public void onClick(View v) {
Log.e("Demo", "点击事件" + "onClick"+v);
}
@Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("Demo", "触摸事件" + "onTouch"+v);
return false;
}
}
xml version="1.0" encoding="utf-8"?>
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/relative_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="按钮" />
这些代码很简单,入门了的人都看得懂。下面是我验证的几个要点:
1、onTouchEvent 返回ture代表消费了此事件,不再传递给上层的GroupView(默认返回false)。
2、dispatchTouchEvent 返回true(Action_Down),后续事件(Action_move、up)都不会传递过来(默认是返回false)。
3、onInterceptTouchEvent 返回true(Action_Down),拦截事件,此事件不会分发到childView中(默认返回false)。
将MyRelativeLayout的dispatchTouchEvent方法的返回值设为true。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
super.onInterceptTouchEvent(ev);
return true;
}
运行结果:
Logcat中没有出现Button相关的日志,整个流程是ACTION_DOWN dispatchTouchEvent --> ACTION_DOWN onTouchEvent --> ACTION_UP dispatchTouchEvent --> ACTION_UP onTouchEvent。
4、如果所有的view、或者viewgroup都没有消费onTouchEvent事件(Action_Down),后续的事件都不会再被传递(Action_move、up)。
将MyButton和MyRelativeLayout中的onTouchEvent方法的返回值都改成false
@Override
public boolean onTouchEvent(MotionEvent event) {
//触摸
Log.e("Demo", "Button --> onTouchEvent" + event.getAction() + "");
super.onTouchEvent(event);
return false;
}
运行结果如下:
RelativeLayout和Button都执行了onTouchEvent,处理的事件只有0(Action_down)。