Android事件分发机制------------>验证+理解
16lz
2021-01-26
View的事件分发机制的总结:
MotionEvent:
- ACTION_DOWN—手指刚接触屏幕;
- ACTION_MOVE—-手指在屏幕上移动;
ACTION_UP——-手机从屏幕上松开的一瞬间;
点击屏幕离开后松开,事件序列为DOWN->UP;
点击屏幕滑动一会再松开,事件序列为DOWN->MOVE->….MOVE->UP.
@Api
- public boolean dispatchTouchEvent(MotionEvent ev);
用来进行事件的分发。如果事件能够传递当前View,那么此方法一定会被调用,返回结果当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。 - public boolean onInterceptTouchEvent(MotionEvent event);
用来判断是否拦截某个事件,true–>自行处理,false–>继续向下派发。 - public boolean onTouchEvent(MotionEvent event);
判断是否消费,true–>消费,false–>不消费,继续向上级提交。
总结:
隧道式派发,冒泡式消费。
理解记忆:
派发:Activity—>ViewGroup—–>View
消费:View–>ViewGroup—>Activity
写一个Demo验证理解:
MainActivity:
package com.example.vieweventdemo;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.MotionEvent;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { //提示:MotionEvent.ACTION_DOWN=0; Log.e("MainActivity", "触发MainActivityev--->"+ev.getAction()); return super.dispatchTouchEvent(ev); }}
再写一个FatherView
package com.example.vieweventdemo;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;import android.widget.RelativeLayout;public class FatherView extends RelativeLayout { public FatherView(Context context) { super(context); // TODO Auto-generated constructor stub } public FatherView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public FatherView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub } //是否结束继续派发 @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.e("MainActivity", "经过了FatherView,dispatchTouchEvent---->"); return super.dispatchTouchEvent(ev); } //判断是否拦截--》true:拦截,false继续派发 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.e("MainActivity", "经过了FatherView,onInterceptTouchEvent---->"); return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.e("MainActivity", "经过了FatherView,onTouchEvent---->"); return super.onTouchEvent(event); }}
最后一个ChildView
package com.example.vieweventdemo;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
public class ChildView extends TextView {
public ChildView(Context context) { super(context); // TODO Auto-generated constructor stub}public ChildView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub}public ChildView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub}// 是否结束继续派发@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) { Log.e("MainActivity", "经过了ChildView,dispatchTouchEvent---->"); return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) { Log.e("MainActivity", "经过了ChildView,onTouchEvent---->消费了"); return true;}
}
布局文件: "http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/real" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.vieweventdemo.MainActivity" > "match_parent" android:layout_height="match_parent" android:gravity="center" android:background="#0f0" > "200dp" android:layout_height="200dp" android:text="textview" android:layout_gravity="center" android:background="#f00" /> ----------第一种情况。。。最底层view消费了事件05-02 08:56:36.416: E/MainActivity(1792): 触发MainActivityev--->005-02 08:56:36.416: E/MainActivity(1792): 经过了FatherView,dispatchTouchEvent---->05-02 08:56:36.420: E/MainActivity(1792): 经过了FatherView,onInterceptTouchEvent---->05-02 08:56:36.420: E/MainActivity(1792): 经过了ChildView,dispatchTouchEvent---->05-02 08:56:36.420: E/MainActivity(1792): 经过了ChildView,onTouchEvent---->消费了05-02 08:56:36.532: E/MainActivity(1792): 触发MainActivityev--->105-02 08:56:36.532: E/MainActivity(1792): 经过了FatherView,dispatchTouchEvent---->05-02 08:56:36.532: E/MainActivity(1792): 经过了FatherView,onInterceptTouchEvent---->05-02 08:56:36.532: E/MainActivity(1792): 经过了ChildView,dispatchTouchEvent---->05-02 08:56:36.532: E/MainActivity(1792): 经过了ChildView,onTouchEvent---->消费了
第二种情况:最底层view不消费事件。
05-02 09:05:09.821: E/MainActivity(1873): 触发MainActivityev--->005-02 09:05:09.821: E/MainActivity(1873): 经过了FatherView,dispatchTouchEvent---->05-02 09:05:09.821: E/MainActivity(1873): 经过了FatherView,onInterceptTouchEvent---->05-02 09:05:09.821: E/MainActivity(1873): 经过了ChildView,dispatchTouchEvent---->05-02 09:05:09.821: E/MainActivity(1873): 经过了ChildView,onTouchEvent---->不消费05-02 09:05:09.821: E/MainActivity(1873): 经过了FatherView,onTouchEvent---->05-02 09:05:09.945: E/MainActivity(1873): 触发MainActivityev--->1
其他情况不试了。
总结:
隧道式分发,冒泡式消费。
换角度,以下是个人理解。
return true ——>“事件停止工作”。
return false ——>“事件继续工作”。
验证+理解_第1张图片" title="" width="337" height="481" style="border:1px solid black;">
如果发现有错,请指导!非常感激!
喜欢的赞一个。
更多相关文章
- Android(安卓)事件分发机制(最新源码6.0分析)--ViewGrop
- Android触发器组件BroadcastReceiver详解
- Android(安卓)API Guides---Calendar Provider
- Android控件:EditText之setOnEditorActionListener的使用
- Android(安卓)webkit 事件传递流程通道分析
- android中的 touch事件
- Android实现机制(三)——View事件分发机制
- 安卓003快速入门
- 第一章:初入Android大门(Style 样式和Button事件)