Android触摸事件的分发、拦截、处理

 在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)。

你可能感兴趣的:(android)