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

小菜鸟战斗机 2018-3-27 181

在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"?><com.example.myinflatedemo.MyRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/relative_layout"    android:layout_width="match_parent"    android:layout_height="match_parent">    <com.example.myinflatedemo.MyButton        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="按钮" /></com.example.myinflatedemo.MyRelativeLayout>

这些代码很简单,入门了的人都看得懂。

下面是我验证的几个要点:

1、onTouchEvent 返回ture代表消费了此事件,不再传递给上层的GroupView(默认返回false)。

2、dispatchTouchEvent 返回true(Action_Down),后续事件(Action_move、up)都不会传递过来(默认是返回false)。

3、onInterceptTouchEvent 返回true(Action_Down),拦截事件,此事件不会分发到childView中(默认返回false)。

将MyRelativeLayout的dispatchTouchEvent方法的返回值设为true。

@Overridepublic 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

@Overridepublic boolean onTouchEvent(MotionEvent event) {    //触摸    Log.e("Demo", "Button --> onTouchEvent" + event.getAction() + "");    super.onTouchEvent(event);    return false;}

运行结果如下:



RelativeLayout和Button都执行了onTouchEvent,处理的事件只有0(Action_down)。


最新回复 (0)
返回