Android View 事件分发机制 && Android ViewGroup 事件分发机制 源码解析 --总结
来源:互联网 发布:数据魔方 免费 编辑:程序博客网 时间:2024/06/09 01:26
Android View 事件分发机制
1、整个View的事件转发流程是:
View.dispatchEvent->View.setOnTouchListener->View.onTouchEvent
在dispatchTouchEvent中会进行OnTouchListener的判断,如果OnTouchListener不为null且返回true,则表示事件被消费,onTouchEvent不会被执行;否则执行onTouchEvent。
2、onTouchEvent中的DOWN,MOVE,UP
DOWN时:
a、首先设置标志为PREPRESSED,设置mHasPerformedLongPress=false ;然后发出一个115ms后的mPendingCheckForTap;
b、如果115ms内没有触发UP,则将标志置为PRESSED,清除PREPRESSED标志,同时发出一个延时为500-115ms的,检测长按任务消息;
c、如果500ms内(从DOWN触发开始算),则会触发LongClickListener:
此时如果LongClickListener不为null,则会执行回调,同时如果LongClickListener.onClick返回true,才把mHasPerformedLongPress设置为true;否则mHasPerformedLongPress依然为false;
MOVE时:
主要就是检测用户是否划出控件,如果划出了:
115ms内,直接移除mPendingCheckForTap;
115ms后,则将标志中的PRESSED去除,同时移除长按的检查:removeLongPressCallback();
UP时:
a、如果115ms内,触发UP,此时标志为PREPRESSED,则执行UnsetPressedState,setPressed(false);会把setPress转发下去,可以在View中复写dispatchSetPressed方法接收;
b、如果是115ms-500ms间,即长按还未发生,则首先移除长按检测,执行onClick回调;
c、如果是500ms以后,那么有两种情况:
i.设置了onLongClickListener,且onLongClickListener.onClick返回true,则点击事件OnClick事件无法触发;
ii.没有设置onLongClickListener或者onLongClickListener.onClick返回false,则点击事件OnClick事件依然可以触发;d、最后执行mUnsetPressedState.run(),将setPressed传递下去,然后将PRESSED标识去除;
最后问个问题,然后再运行个例子结束:
1、setOnLongClickListener和setOnClickListener是否只能执行一个
不是的,只要setOnLongClickListener中的onClick返回false,则两个都会执行;返回true则会屏幕setOnClickListener
最后我们给MyButton同时设置setOnClickListener和setOnLongClickListener,运行看看:
package com.example.zhy_event03;import android.app.Activity;import android.os.Bundle;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.View.OnClickListener;import android.view.View.OnLongClickListener;import android.view.View.OnTouchListener;import android.widget.Button;import android.widget.Toast;public class MainActivity extends Activity{protected static final String TAG = "MyButton";private Button mButton ;@Overrideprotected void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mButton = (Button) findViewById(R.id.id_btn);mButton.setOnTouchListener(new OnTouchListener(){@Overridepublic boolean onTouch(View v, MotionEvent event){int action = event.getAction();switch (action){case MotionEvent.ACTION_DOWN:Log.e(TAG, "onTouch ACTION_DOWN");break;case MotionEvent.ACTION_MOVE:Log.e(TAG, "onTouch ACTION_MOVE");break;case MotionEvent.ACTION_UP:Log.e(TAG, "onTouch ACTION_UP");break;default:break;}return false;}});mButton.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v){Toast.makeText(getApplicationContext(), "onclick",Toast.LENGTH_SHORT).show();}});mButton.setOnLongClickListener(new OnLongClickListener(){@Overridepublic boolean onLongClick(View v){Toast.makeText(getApplicationContext(), "setOnLongClickListener",Toast.LENGTH_SHORT).show();return false;}});}}效果图:
可以看到LongClickListener已经ClickListener都触发了~
Android ViewGroup事件分发机制
1、如果ViewGroup找到了能够处理该事件的View,则直接交给子View处理,自己的onTouchEvent不会被触发;
2、可以通过复写onInterceptTouchEvent(ev)方法,拦截子View的事件(即return true),把事件交给自己处理,则会执行自己对应的onTouchEvent方法
3、子View可以通过调用getParent().requestDisallowInterceptTouchEvent(true); 阻止ViewGroup对其MOVE或者UP事件进行拦截;
好了,那么实际应用中能解决哪些问题呢?
比如你需要写一个类似slidingmenu的左侧隐藏menu,主Activity上有个Button、ListView或者任何可以响应点击的View,你在当前View上死命的滑动,菜单栏也出不来;因为MOVE事件被子View处理了~ 你需要这么做:在ViewGroup的dispatchTouchEvent中判断用户是不是想显示菜单,如果是,则在onInterceptTouchEvent(ev)拦截子View的事件;自己进行处理,这样自己的onTouchEvent就可以顺利展现出菜单栏了~~
- Android View 事件分发机制 && Android ViewGroup 事件分发机制 源码解析 --总结
- Android View 事件分发机制 源码解析(ViewGroup篇)
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View 事件分发机制 源码解析
- Android View、ViewGroup 事件分发机制(一)
- Android View、ViewGroup 事件分发机制(二)
- Android ViewGroup/View 事件分发机制详解
- Android View 和 ViewGroup 事件分发机制
- Android View和ViewGroup事件分发机制源码分析
- Android View 事件分发机制源码详解(ViewGroup篇)
- Android View和ViewGroup事件分发机制源码分析
- Struts2图片文件上传,判断图片格式和图片大小
- i++和++i区别
- Xcode各个版本下载地址
- git fetch /rebase /merge 使用
- spring-mvc.xml文件的配置(官方文件)
- Android View 事件分发机制 && Android ViewGroup 事件分发机制 源码解析 --总结
- doT.js初窥
- HDU 5194 DZY Loves Balls
- 1013. Battle Over Cities (25) 连通子集 连通分量的数量
- Android 布局优化
- 为什么这段代码输出的是”Hello World”
- ABAP 报表求和统计功能实现方法
- Java多线程文件下载
- JavaMelody Maven 配置 及简单应用