【Android】View的事件分发机制123
来源:互联网 发布:电力线路设计软件 编辑:程序博客网 时间:2024/06/14 18:24
1.通过日志来分析事件传递相关方法的执行流程
为了更好的了解view的事件传递,我们可以自定义一个button继承自Button,并重写事件传递相关方法通过打日志来分析各个方法的执行顺序。
自定义button,重写dispatchTouchEvent和onTouchEvent
public class MyButton extends Button { public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d("dispatchTouchEvent", "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.d("dispatchTouchEvent", "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.d("dispatchTouchEvent", "ACTION_UP"); break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.d("onTouchEvent", "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.d("onTouchEvent", "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.d("onTouchEvent", "ACTION_UP"); break; } return super.onTouchEvent(event); }}
将自定义button添加到布局中
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.tfx.test.MainActivity"> <com.tfx.test.MyButton android:id="@+id/bt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button"/></LinearLayout>
MainActivity代码,给自定义button注册setOnTouchEvent监听
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = (Button) findViewById(R.id.bt); button.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: Log.d("onTouch", "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.d("onTouch", "ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.d("onTouch", "ACTION_UP"); break; } return false; } }); }}重写了三个事件分发相关方法后,运行demo并单击button按钮,然后看输出的日志
12-19 09:22:56.478 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_DOWN12-19 09:22:56.478 1837-1837/com.tfx.test D/onTouch: ACTION_DOWN12-19 09:22:56.478 1837-1837/com.tfx.test D/onTouchEvent: ACTION_DOWN12-19 09:22:56.556 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_UP12-19 09:22:56.556 1837-1837/com.tfx.test D/onTouch: ACTION_UP12-19 09:22:56.556 1837-1837/com.tfx.test D/onTouchEvent: ACTION_UP如果点击按钮时手指稍微蹭一下,会执行多次move,如下
12-19 09:20:17.253 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_DOWN12-19 09:20:17.253 1837-1837/com.tfx.test D/onTouch: ACTION_DOWN12-19 09:20:17.253 1837-1837/com.tfx.test D/onTouchEvent: ACTION_DOWN12-19 09:20:17.295 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_MOVE12-19 09:20:17.296 1837-1837/com.tfx.test D/onTouch: ACTION_MOVE12-19 09:20:17.296 1837-1837/com.tfx.test D/onTouchEvent: ACTION_MOVE12-19 09:20:17.463 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_MOVE12-19 09:20:17.463 1837-1837/com.tfx.test D/onTouch: ACTION_MOVE12-19 09:20:17.463 1837-1837/com.tfx.test D/onTouchEvent: ACTION_MOVE12-19 09:20:17.580 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_MOVE12-19 09:20:17.580 1837-1837/com.tfx.test D/onTouch: ACTION_MOVE12-19 09:20:17.580 1837-1837/com.tfx.test D/onTouchEvent: ACTION_MOVE12-19 09:20:17.716 1837-1837/com.tfx.test D/dispatchTouchEvent: ACTION_UP12-19 09:20:17.717 1837-1837/com.tfx.test D/onTouch: ACTION_UP12-19 09:20:17.717 1837-1837/com.tfx.test D/onTouchEvent: ACTION_UP从日志我们大致可以看出,不管是down、move、up执行的流程都是dispatchTouchEvent --> onTouch --> onTouchEvent。
onTouchListener的onTouch方法是有返回值的,如果把返回值改为return true再运行,会发现onTouchEvent方法得不到执行,这是为什么呢?此时若再给按钮注册单击事件,会发现单击事件也不会被触发,这又是为什么呢? 带着这两个问题,接下来我们对dispatchTouchEvent方法进行分析。
2.dispatchTouchEvent方法
进入button的父类TextView我们并没有发现该方法,继续在它的父类view里面找,此时就能看到dispatchTouchEvent方法的源码,如下:
public boolean dispatchTouchEvent(MotionEvent event) { if (!onFilterTouchEventForSecurity(event)) { return false; } if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && mOnTouchListener.onTouch(this, event)) { return true; } return onTouchEvent(event); }主要就看第二个if语句,这里会有三个条件:
条件一:对mOnTouchListener进行非空判断,也就是判断是否注册了onTouchListener监听
条件二:判断view是否是enable,一般控件默认都是enable
条件三:判断onTouchEvent的onTouch方法是否返回true
如果这三个条件都成立,那么dispatchTouchEvent方法就返回true,否则执行onTouchEvent并返回。
接着说上面的第一个问题,当三个条件都满足了,dispatchTouchEvent方法就会返回ture,onTouchEvent方法将得不到执行,也就是说onTouchListener的onTouch方法的返回值决定了onTouchEvent方法能否得到执行,如果返回true事件将会被消费,不再继续传递给onTouchEvent方法,默认返回false,onTouchEvent方法将得到执行,到这里第一个问题就解决了。
接着说问题二,根据问题一,我们可以断定单击事件的onClick方法是在onTouchEvent方法中执行的,只有onTouchEvent方法得到执行,才能响应单击事件。还有onTouch方法的执行优先于onClick方法,onTouch方法做的比onClick更多,能响应dowm、move、up多个手势。
3.onTouchEvent方法
111
0 0
- 【Android】View的事件分发机制123
- android事件分发机制 VIew的事件分发机制
- Android 事件分发机制解析之View的事件分发
- android中view的事件分发机制
- Android之View的事件分发机制
- Android View的事件分发机制
- Android View的事件分发机制
- Android中View的事件分发机制
- Android View的事件分发机制浅析
- android View的事件分发机制
- Android View的事件分发机制
- Android中View的事件分发机制
- Android中View的事件分发机制
- Android View的事件分发机制
- Android中View的事件分发机制
- Android中View的事件分发机制
- Android View Touch的事件分发机制
- Android —View的事件分发机制
- 面试试题
- Lambda语法(上)
- codeforces #386 div2 D. Green and Black Tea
- maven在eclipse中的配置
- bLue的文件查找器
- 【Android】View的事件分发机制123
- MapReduce(一)
- HDP安全架构
- libfacedetection-master+vs2013配置
- [Leetcode] Word Pattern
- Cookie 浅析------初识
- AHK按键转载
- 嵌入式Linux开发第一步:虚拟机安装Ubuntu
- AVL树,红黑树,B树,B+树,Trie树应用场景简介