怀抱观古今,寝食展戏谑。这篇文章主要讲述Android自己定义组件系列——进阶实践相关的知识,希望能为你提供帮助。
上一篇《Android自己定义组件系列【5】——进阶实践(2)》继续对任老师的《可下拉的PinnedHeaderExpandableListView的实现》进行了分析,这一篇计划中间插一段“知识点”,对android中的事件分发机制进行解析。细心的朋友可能会发现,打开大牛写的Android项目,里面非常多组件都是自己定义的(这就是为什么界面和体验这么吸引你的原因),可是要灵活的去自己定义组件就必须对手势(也就是各种监听)必须熟悉,能处理好事件之间的关系。
【Android自己定义组件系列——进阶实践】先看一段代码:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new OnClickListener() {@Override public void onClick(View arg0) { Log.i(TAG, "onClick"); } }); button.setOnTouchListener(new OnTouchListener() {@Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i(TAG, "onTouchdown"); break; case MotionEvent.ACTION_MOVE: Log.i(TAG, "onTouch move"); break; case MotionEvent.ACTION_UP: Log.i(TAG, "onTouch up"); break; default: break; } return false; } }); }
文章图片
能够看到onTouch方法会被先调用。然后才调用onClick方法,假设我们将上面onTouch方法的返回值改为true,则onClick方法不会被调用,事件将被onTouch方法消费。
还记得前几篇文章中都会使用一个dispatchTouchEvent的方法吗.
public boolean dispatchTouchEvent(MotionEvent event) { if (mOnTouchListener != null & & (mViewFlags & ENABLED_MASK) == ENABLED & & mOnTouchListener.onTouch(this, event)) { return true; } return onTouchEvent(event); }
能够看到在dispatchTouchEvent中调用了onTouch方法,所以会先于onClick方法调用。假设onTouch返回true后dispatcheTouchEvent就会直接返回true则不会再运行其它方法。
在Android系统中每一个ViewGroup子类都具有例如以下三个方法:
public boolean dispatchTouchEvent(MotionEvent event) :用来分发TouchEvent
public boolean onInterceptTouchEvent(MotionEvent event) :用来拦截TouchEvent
public boolean onTouchEvent(MotionEvent event) :处理TouchEvent
< ?xml version="1.0" encoding="utf-8"?
> < LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> < com.kris.touch.widget.TouchView android:id="@+id/view_out" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#fff" android:gravity="center"> < com.kris.touch.widget.TouchView android:id="@+id/view_mid" android:layout_width="300px" android:layout_height="400px" android:background="#f00" android:gravity="center"> < com.kris.touch.widget.TouchView android:id="@+id/view_center" android:layout_width="150px" android:layout_height="150px" android:background="#000" android:gravity="center" android:clickable="true"> < /com.kris.touch.widget.TouchView> < /com.kris.touch.widget.TouchView> < /com.kris.touch.widget.TouchView> < /LinearLayout>
文章图片
首先触摸事件(ACTION_DOWN)发生后,系统调用Activity的dispatchTouchEvent方法。分发事件。
依据触摸事件的坐标,将此事件传递给out(最外层)的dispatchTouchEvent处理。out则调用onInterceptTouchEvent方法推断事件是否由自己来处理。还是向下传递给子View.假设out不处理该事件会依据事件产生坐标分发给它的直接子View.
图中center组件是可点击的(clickable)组件,表示能处理Touch事件,所以center中的onInterceptTouchEvent方法将事件传递给center
文章图片
TouchEvent中,假设返回值是true,则说明消耗(消费)了这个事件,不会再向下传递。假设返回值是false,则没有消耗事件,会继续传递下去。假设center中不会处理事件(android:clickable="false")。事件不会被center的onTouchEvent消费,则事件会层层逆向回到activity。
关于事件分发机制就先了解到这里。下一篇接着分析......
推荐阅读
- Android 下拉刷新上拉载入效果功能
- Android 进阶Dagger2 系列(入门案例一)
- 安卓应用方法数超过64k解决办法(分割Dex)
- xp系统防范人生日历升级的办法
- win xp系统下怎样截取WPS表格图片
- win xp系统如何在表格中制作数据条
- win xp系统将matlab数据导入excel的办法
- xp系统stormmedia可以删除吗|xp系统stormmedia文件夹如何删除
- win xp系统如何修正图片中歪掉的水平线【图文详细教程】