Android学习之路--View--事件传递机制
来源:互联网 发布:大数据量化基金 编辑:程序博客网 时间:2024/05/29 18:02
之前我们介绍了安卓的四大组件,接下来我们说说Android的事件传递机制,我们都知道,任何的组件都是在一个laytout里进行摆放的。不管是哪种layout,都是继承自ViewGroup容器。而我们所要研究的也就是从activity—viewgroup–XXXview,一级一级的传递。
事件的传递就好像一个任务下来,总有人要做,我们现在分配3个角色,正好对应不同的层级,大boss领导,中层主管,以及下层小兵。进行这么分配也是为方便理解记忆。
首先,我们首先说说时间分发主要用到的方法:
dispatchTouchEvent:用来判断是否进行事件分发
onInterceptTouchEvent:用来判断是否进行事件拦截
onTouchEvent:用来处理事件行为
1、首先我们有应用程序activity:
public class TestMain extends Activity { private String tag = TestMain.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testevent); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { LogUtil.i(tag,"TestMain dispatchTouchEvent"); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { LogUtil.i(tag,"TestMain onTouchEvent"); return super.onTouchEvent(event); }}
activity里只有这俩个方法,是因为事件要不要分发,要分发就分发,不分发就自己处理。
2、涉及到是ViewGroup容易,这里的存放的都是子view,这里涉及到一个事件的分发,和是否拦截的问题。
public class TestLinearlayout extends LinearLayout { String tag = TestLinearlayout.class.getSimpleName(); public TestLinearlayout(Context context) { super(context); } public TestLinearlayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { LogUtil.i(tag,"+++++++++TestLinearlayout dispatchTouchEvent "); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { LogUtil.i(tag,"++++++++ TestLinearlayout onInterceptTouchEvent "); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { LogUtil.i(tag,"++++++++ TestLinearlayout onTouchEvent "); return super.onTouchEvent(event); }}
这个是layout布局文件,我们引用的时候,就引用当前的layout文件。
3、接下来就是我们自定义的TextView,其实也没啥,就是几个方法。
public class TestTextView extends TextView { String tag = TestTextView.class.getSimpleName(); public TestTextView(Context context) { this(context,null); } public TestTextView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { LogUtil.i(tag, "------TestTextView dispatchTouchEvent "); return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { LogUtil.i(tag, "------TestTextView onTouchEvent "); return true; }}
这是我们最里面的布局。
统一的layout为:
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical"> <com.android.app.view.TestLinearlayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@drawable/myshape" android:gravity="center" android:layout_margin="50dp"> <com.android.app.view.TestTextView android:id="@+id/myview" android:layout_width="200dp" android:layout_height="200dp" android:background="@drawable/myshape" android:text="最小组件" android:gravity="center"/> </com.android.app.view.TestLinearlayout></LinearLayout>
为清晰的显示我们的组件边间,加一个背景shape:
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:color="@color/colorPrimary" android:width="1px"></stroke> <solid android:color="@color/white"></solid></shape>
页面效果看起来是这个样子的:
注:最外面的就是咱们的activity界面了,中间的边框就是我们layout,里面的框就是我们的textView了。
接下来,我们就开始点击各种事件,看下Event是怎么传递的了。
有一下几种case:
1、首先,我们点击最外面的activity,日志如下:
1·1 都是正常的返回的都是super
I/TestMain: TestMain dispatchTouchEventI/TestLineayout: TestLinearlayout dispatchTouchEventI/TestLinearlayout: TestLinearlayout onInterceptTouchEventI/TestTextView: TestTextView dispatchTouchEventI/TestTextView: TestTextView onTouchEventI/TestLinearlayout: TestLinearlayout onTouchEventI/TestMain: TestMain onTouchEvent
#我们看到事件都是一级一级向下传递,然后在向上传递
1·2如果activity中的dispatchTouchEvent返回true,则打印
I/TestMain: TestMain dispatchTouchEvent
相当于当前累消费了此事件,就是我能干这件事不用下边的人干,不在放下传递
1.3如果activity中的dispatchTouchEvent返回false,则打印:
I/TestMain: TestMain dispatchTouchEvent
相当于当前类消费事件不在往下传递。
2、我们在点击,layout中的参数设置:
2.1 正常super传递,则和1.1一样,事件正常传递
2.2 layout.dispatchTouchEvent 返回ture时,则打印:
I/TestMain: TestMain dispatchTouchEventI/TestLinearlayout: TestLinearlayout dispatchTouchEvent
相当于当前类消费了此事件,不往下下传递。翻译过来就是领导先不干,让下边的人干, 结果主管一看,擦,自己不干,也没让下面的人干,也没返给领导到底干了没干。
2.3 layout.dispatchTouchEvent,如果返回false,则打印:
I/TestMain: TestMain dispatchTouchEvent I/TestLinearlayout: TestLinearlayout dispatchTouchEvent I/TestMain: TestMain onTouchEvent
相当于当前累没有消费此事件,但是不在继续分发,直接返回让父类消费。翻译过来就是领导先不干,让下边的人干, 结果主管一看也干不了,那下面的人就更干不了了,返回给领导,领导说,擦,这帮废物,还得我自己干,执行容器ontouchevent方法
2.4 layout.dispatchTouchEvent 返回super类,继续向下传递,但layout.onInterceptTouchEvent 返回true,则打印:
I/TestMain: TestMain dispatchTouchEventI/TestLinearlayout: TestLinearlayout dispatchTouchEventI/TestLinearlayout: TestLinearlayout onInterceptTouchEventI/TestLinearlayout: TestLinearlayout onTouchEventI/TestMain: TestMain onTouchEvent
此类有能力消费了此事件,拦截,不往下下传递。翻译过来就是领导先不干,让下边的人干, 结果主管一看,汗,简单,能干,那就拦截,自己先处理了这件事, layout.touch事件就是主管在处理事情,如果处理成功, 返回true,就不会执行父类的ontouch方法,就是我处理了,你不用在处理了,如果返回false,相当于我处理了一顿结果还没处理成。还得让父类解决,就继续执行父类的onTouchevent方法,即TestMain onTouchEvent。(此时:TestLinearlayout onTouchEvent方法返回false和super的作用一致,都是我处理不了)
2.5 类还原初始化,layout.dispatchTouchEvent 返回super类,继续向下传递,但layout.onInterceptTouchEvent 返回false,则打印:
I/TestMain: TestMain dispatchTouchEventI/TestLinearlayout: TestLinearlayout dispatchTouchEvent I/TestLinearlayout: TestLinearlayout onInterceptTouchEvent I/TestTextView: TestTextView dispatchTouchEvent I/TestTextView: TestTextView onTouchEvent I/TestLinearlayout:TestLinearlayout onTouchEvent I/TestMain: TestMain onTouchEvent
此类暂时不知道能不能干,继续向下传递,让手下先干的,我不进行拦截。看下面的人办的怎么样。(因为我们都是返回的super,在这里我们可以认为手下处理不了,返回主管处理不了,返回领导,让领导处理,这就是打印的全过程)。
3、textview中的参数设置
3.1 正常super传递,则和1.1一样,事件正常传递
3.2 textview.dispatchTouchEvent 返回ture时,则打印
I/TestMain: TestMain dispatchTouchEventI/TestLinearlayout: TestLinearlayout dispatchTouchEvent I/TestLinearlayout: TestLinearlayout onInterceptTouchEvent I/TestTextView: TestTextView dispatchTouchEvent
此类消费了事件,不进行传递,和2.2一样,只不过角色换成了手下,你说气不气人,你干成干不成总有个回话了吧,上头也不知道个结果
3.3 textview.dispatchTouchEvent 返回false时,则打印:
I/TestMain: TestMain dispatchTouchEventI/TestLinearlayout: TestLinearlayout dispatchTouchEvent I/TestLinearlayout:TestLinearlayout onInterceptTouchEvent I/TestTextView:TestTextView dispatchTouchEvent I/TestLinearlayout:TestLinearlayout onTouchEvent I/TestMain: TestMain onTouchEvent
即当前类没有消费此事件,返回给父类消费,翻译过来就是:分给我了任务,我一看结局不了,立马返给主管,让主管解决,主管解决的情况如何看2.4layout.touchevent 返回解释。
3.4 textview.dispatchTouchEvent 返回super,ontouch事件返回true时,则打印:
I/TestMain: TestMain dispatchTouchEventI/TestLinearlayout: TestLinearlayout dispatchTouchEvent I/TestLinearlayout: TestLinearlayout onInterceptTouchEvent I/TestTextView: TestTextView dispatchTouchEvent I/TestTextView: TestTextView onTouchEvent
即当前类有能力消费此事件。不在向上级传递。翻译过来就是:领导先不干,传给主管,主管懒的看也不看,一下传给手下,手下一看,这么简单,我能处理,就处理了,返回true。就是我处理了此事,你们不用再处理了,如果返回false,就是说我处理了一顿也没处理,在返给主管吧,主管的处理情况见2.4解释翻译。
好了,Android之View事件机制说了这么多,估计大家也有点绕。自己敲的代码自己亲自测试下。增进下了解与记忆,并且结合源码,自己实践下。我也不放整个项目了,就放几个简单的文件,方便下懒人大神吧。
View的机制是安卓中的难点,这个得慢慢消化,并且这方面的知识在面试中也是经常问到的问题。还需大家要多多研究啊!
2017年第一份知识记录,好几天没写了,这几天赶紧补上。也㊗️大家2017技术上多多增进,知识慢慢积累。早日铸就高塔。
- Android学习之路--View--事件传递机制
- Android自定义view之事件传递机制
- Android进阶学习之路——View事件的传递机制
- Android View 事件传递机制
- Android View事件传递机制
- Android-view事件传递机制
- 【Android View】 事件传递机制
- Android学习之 Touch事件传递机制
- android view的事件传递机制学习笔记
- Android事件传递机制-View篇
- Android中的View事件传递机制
- Android事件传递机制-View篇
- Android事件传递机制-View篇
- Android View 触摸事件传递机制
- Android View触摸事件传递机制
- Android事件传递机制-View篇
- Android View触摸事件传递机制
- Android View事件传递机制-源码分析
- bzoj 1337: 最小圆覆盖 (最小圆覆盖)
- #Andriod 关于拍照及本地图片多选的那些事(上)
- 服务器性能优化和Mysql性能优化
- cocos2d-x面试题(一)
- IplImage 和 QImage的转换 (转:http://blog.sina.com.cn/s/blog_5c70dfc80100qzif.html)
- Android学习之路--View--事件传递机制
- Leetcode 164 Maximum Gap 桶排序好题
- 【Unity经验】委托与事件
- 整理了以下四种在MySQL中修改root密码的方法,可能对大家有所帮助!
- 解决MFC项目使用多字节字符集后软件界面风格发生改变的问题
- 457_自动滚动的ViewPager
- 深入理解Spark 2.1 Core (六):资源调度的原理与源码分析
- C++面试题(六)
- ECMAScript 6(2)let和块级作用域