Android事件分发机制之View篇

           Android事件分发机制之View篇

我们在android手机开发中有时会碰到一些这样的问题:1、上下滑动屏幕,ListView并不随之滚动?2、按一些按键(如Button),且已经设置了setOnclickListener相关监听,但按键确实没反应?这是为什么呢?这就是我这篇文章要讲到的Android事件分发。我们通过一个非常简单的例子来讲解一下,这个真的是非常简单:

先来一个Demo示范:
界面非常简单,就一个按钮如下:
一、Demo的layout文件

activity_main.xml文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >

    <cn.ithm.eventdemo.MyButton
        android:id="@+id/mybutton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</LinearLayout>

二、自定义Button
MyButton类文件如下:

public class MyButton extends Button {

    private static final String TAG = "MyButton";

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyButton dispatchTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyButton dispatchTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.dispatchTouchEvent(event);
//      return true;
    }



    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MyButton onTouchEvent--ACTION_DOWN");

            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MyButton onTouchEvent--ACTION_UP");

            break;

        default:
            break;
        }
        return super.onTouchEvent(event);
    }

}

三、MainActivity.java文件如下:

public class MainActivity extends Activity {

    protected static final String TAG = "MainActivity";
    private Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.mybutton);

        button.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                Log.i(TAG, "MyButton onclick");
            }
        });

        button.setOnTouchListener(new OnTouchListener() {

            @Override
            public boolean onTouch(View arg0, MotionEvent arg1) {
                switch (arg1.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    Log.i(TAG, "MyButton setOnTouchListener--ACTION_DOWN");

                    break;
                case MotionEvent.ACTION_UP:

                    Log.i(TAG, "MyButton setOnTouchListener--ACTION_UP");
                    break;

                default:
                    break;
                }

                return false;
//              return true;
            }
        });
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            Log.i(TAG, "MainActivity dispatchTouchEvent--ACTION_DOWN");
            break;
        case MotionEvent.ACTION_UP:
            Log.i(TAG, "MainActivity dispatchTouchEvent--ACTION_UP");
            break;

        default:
            break;
        }
        return super.dispatchTouchEvent(ev);
//      return true;
    }


}
我们准备好上面文件后,就开始研究我们的事件分发了。首先我们点击“hello word”这个按键后,LogCat里打印出如下结果:
![这里写图片描述](https://img-blog.csdn.net/20151226174624368)

从上面的结果我们可以看出,android事件分发的起点是Activity自身的dispatchTouchEvent方法开始的,然后到子View的dispatchTouchEvent->onTouch->onTouchEvent,再是up事件,跟down顺序是相同的,最后执行MyButton的onClick事件。

到这里我们大概清楚了android的事件分发是如何执行的。接下来我们对代码稍作修改,只是把Activity中的dispatchTouchEvent的返回值作一个修改,让其return true; 然后我们再看LogCat的打印结果:
这里写图片描述
从上面这个结果,我们大吃一惊,后续的touch事件都没有执行。这是什么原因呢?其实很简单啦,就是Activity的dispatchTouchEvent的返回值惹的事,它返回了true,表示Activity已经把事件给消耗掉了,后续的子View不能接收到事件了,所以后面的都没有执行。
好,非常好!我们接下来把代码恢复为最初的模样,然后再button.setOnTouchListener方法中返回true,运行再看打印结果:
这里写图片描述
我们发现MyButton的onTouchEvent和onClick都没有执行,也是同样的道理,MyButton在onTouch中把事件消耗掉了所以不再往下发了。

四、总结
通过这个简单的demo例子,我们总结如下:
1、Android事件分发之View的顺序是Activity的dispatchTouchEvent->子View的dispatchTouchEvent->子View的OnTouch->子View的onTouchEvent->onClick
2、事件分发是顺序执行的,如果在某一点事件事件被消耗了,则事件不会再往后传了

最后,由于我刚学安卓不久,以上内容写的不好的地方,请批评指正!谢谢

猜你喜欢

转载自blog.csdn.net/wufeiqing/article/details/50409458