您的位置:首页 > 移动开发 > Android开发

Android事件分发机制之View篇

2015-12-26 17:49 549 查看
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、事件分发是顺序执行的,如果在某一点事件事件被消耗了,则事件不会再往后传了

最后,由于我刚学安卓不久,以上内容写的不好的地方,请批评指正!谢谢
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息