Android:onInterceptTouchEvent 和dispatchTouchEvent 之间的区别
在Android开发中,onInterceptTouchEvent和dispatchTouchEvent是两个常用的触摸事件处理方法。虽然它们都用于处理触摸事件,但它们在处理事件时的作用和方式有所不同。首先,我们需要了解一下触摸事件的传递机制。当用户在屏幕上进行触摸操作时,触摸事件会从父容器开始向子容器传递,直到找到合适的View来处理该事件。这个传递过程中,onInterceptTouchEvent和dispatchTouchEvent扮演了重要的角色。onInterceptTouchEvent:onInterceptTouchEvent方法是ViewGroup类中的一个方法,它用于判断是否拦截触摸事件。当ViewGroup的onInterceptTouchEvent方法返回true时,表示该ViewGroup会拦截触摸事件,不将事件传递给子View处理;当返回false时,表示该ViewGroup不拦截触摸事件,将事件传递给子View处理;当返回super.onInterceptTouchEvent(ev)时,表示该ViewGroup会调用父类的onInterceptTouchEvent方法来处理触摸事件。dispatchTouchEvent:dispatchTouchEvent方法是View类中的一个方法,它用于触摸事件的分发。当View的dispatchTouchEvent方法返回true时,表示该View处理了该事件,不再向上传递;当返回false时,表示该View不处理该事件,将事件继续向上传递。在理解了这两个方法的作用后,我们可以通过一个案例来更好地理解它们之间的区别。假设我们有一个自定义的ViewGroup,该ViewGroup包含了两个子View:一个TextView和一个Button。我们想实现的效果是,当用户点击TextView时,TextView处理该事件;当用户点击Button时,Button处理该事件。下面是我们自定义的ViewGroup的代码:javapublic class CustomViewGroup extends ViewGroup { private TextView textView; private Button button; public CustomViewGroup(Context context) { super(context); initView(context); } public CustomViewGroup(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public CustomViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initView(context); } private void initView(Context context) { textView = new TextView(context); textView.setText("TextView"); addView(textView); button = new Button(context); button.setText("Button"); addView(button); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int top = 0; for (int i = 0; i < childCount; i++) { View childView = getChildAt(i); childView.layout(l, top, r, top + childView.getMeasuredHeight()); top += childView.getMeasuredHeight(); } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.d("CustomViewGroup", "onInterceptTouchEvent: ACTION_DOWN"); return false; case MotionEvent.ACTION_MOVE: Log.d("CustomViewGroup", "onInterceptTouchEvent: ACTION_MOVE"); return false; case MotionEvent.ACTION_UP: Log.d("CustomViewGroup", "onInterceptTouchEvent: ACTION_UP"); return false; } return super.onInterceptTouchEvent(ev); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.d("CustomViewGroup", "dispatchTouchEvent: ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.d("CustomViewGroup", "dispatchTouchEvent: ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.d("CustomViewGroup", "dispatchTouchEvent: ACTION_UP"); break; } return super.dispatchTouchEvent(ev); }}在上述代码中,我们重写了CustomViewGroup的onInterceptTouchEvent和dispatchTouchEvent方法。在onInterceptTouchEvent方法中,我们打印了不同事件的日志,并根据事件类型返回了不同的值;在dispatchTouchEvent方法中,我们也打印了不同事件的日志。接下来,我们在Activity中使用该自定义的ViewGroup,并为TextView和Button设置点击事件:javapublic class MainActivity extends AppCompatActivity { private CustomViewGroup customViewGroup; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); customViewGroup = findViewById(R.id.custom_view_group); customViewGroup.textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "TextView clicked", Toast.LENGTH_SHORT).show(); } }); customViewGroup.button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "Button clicked", Toast.LENGTH_SHORT).show(); } }); }}通过运行上述代码,我们可以看到以下结果:1. 当点击TextView时,日志输出为:onInterceptTouchEvent: ACTION_DOWNdispatchTouchEvent: ACTION_DOWNdispatchTouchEvent: ACTION_UP同时,弹出了一个Toast提示"TextView clicked"。2. 当点击Button时,日志输出为:
onInterceptTouchEvent: ACTION_DOWNdispatchTouchEvent: ACTION_DOWNdispatchTouchEvent: ACTION_UP同时,弹出了一个Toast提示"Button clicked"。从上述结果可以看出,当我们点击TextView时,onInterceptTouchEvent方法返回了false,表示不拦截触摸事件,将事件传递给子View处理。而当我们点击Button时,onInterceptTouchEvent方法同样返回了false,表示不拦截触摸事件,将事件传递给子View处理。在dispatchTouchEvent方法中,我们可以看到ACTION_DOWN和ACTION_UP事件的日志输出,说明触摸事件被正确地传递给了子View进行处理。因此,可以出onInterceptTouchEvent方法用于判断是否拦截触摸事件,而dispatchTouchEvent方法用于触摸事件的分发。