Android View,ViewGroup 事件分发
2015-11-27 18:23
465 查看
虽然一直原来也有看过相关方面的资料,并且用到的也不少了, 但是还是记一记吧, 希望大家都能明白理解
View 继承
Drawable.Callback,
KeyEvent.Callback,
AccessibilityEventSource
ViewRootImpl
frameworks/base/core/java/android/view/ViewRootImpl.java
View
frameworks/base/core/java/android/view/View.java
事件的传递(是由最外层的view 最先获取到)
ViewGroup - ViewGroup - view
View中的方法
事件分发
事件拦截(默认返回false)
事件处理(默认返回false)
* 默认的分发 和处理结合起来,就类似是个闭环*
1
1.1 进入 最顶层父View 的 dispatchTouchEvent 进行事件分发
true 交给本身处理(进入onTouchEvent)
false 进入(方法onInterceptTouchEvent) 看是否拦截事件
如果拦截 返回true - (进入本View onTouchEvent)
不拦截 返回false - (传给子View)
1.2 子View相同判断
1.3 如果View发现自己没有子View 时,则自己处理。
2
2.1 如果子View的 onTouchEvent
返回false (既不做处理) onTouchEvent 事件会向父View传递,并由父View的onTouchEvent 接受
返回true (做处理) 既交给自身的 onTouchEvent 处理
当某个view 拦截,并且处理onTouchEvent
1. 源码 View 是如何获得 事件消息的
1.1 view 的初始化
1.2 attachInfo 的获取
1.3获得 ViewRootImpl
1.4 View 的 dispatchPointerEvent (这个就是传进来的重点了),得到了 dispatchTouchEvent 获得 MotionEvent
1.5接下来 dispatchTouchEvent ,会陆续传给其他
View 继承
Drawable.Callback,
KeyEvent.Callback,
AccessibilityEventSource
ViewRootImpl
frameworks/base/core/java/android/view/ViewRootImpl.java
View
frameworks/base/core/java/android/view/View.java
事件的传递(是由最外层的view 最先获取到)
ViewGroup - ViewGroup - view
View中的方法
事件分发
public boolean dispatchTouchEvent(MotionEvent ev)
事件拦截(默认返回false)
public boolean onInterceptTouchEvent(MotionEvent ev)
事件处理(默认返回false)
public boolean onTouchEvent(MotionEvent ev)
* 默认的分发 和处理结合起来,就类似是个闭环*
1
1.1 进入 最顶层父View 的 dispatchTouchEvent 进行事件分发
true 交给本身处理(进入onTouchEvent)
false 进入(方法onInterceptTouchEvent) 看是否拦截事件
如果拦截 返回true - (进入本View onTouchEvent)
不拦截 返回false - (传给子View)
1.2 子View相同判断
1.3 如果View发现自己没有子View 时,则自己处理。
2
2.1 如果子View的 onTouchEvent
返回false (既不做处理) onTouchEvent 事件会向父View传递,并由父View的onTouchEvent 接受
返回true (做处理) 既交给自身的 onTouchEvent 处理
当某个view 拦截,并且处理onTouchEvent
1. 源码 View 是如何获得 事件消息的
1.1 view 的初始化
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { // 初始化 public View(Context context, AttributeSet attrs, int defStyle) { // View() { mResources = null; }
1.2 attachInfo 的获取
/** * @param info the {@link android.view.View.AttachInfo} to associated with * this view */ void dispatchAttachedToWindow(AttachInfo info, int visibility) { //System.out.println("Attached! " + this); mAttachInfo = info; mWindowAttachCount++; // We will need to evaluate the drawable state at least once. mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY; if (mFloatingTreeObserver != null) { info.mTreeObserver.merge(mFloatingTreeObserver); mFloatingTreeObserver = null; } if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) { mAttachInfo.mScrollContainers.add(this); mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED; } performCollectViewAttributes(mAttachInfo, visibility); onAttachedToWindow(); ListenerInfo li = mListenerInfo; final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners = li != null ? li.mOnAttachStateChangeListeners : null; if (listeners != null && listeners.size() > 0) { // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to // perform the dispatching. The iterator is a safe guard against listeners that // could mutate the list by calling the various add/remove methods. This prevents // the array from being modified while we iterate it. for (OnAttachStateChangeListener listener : listeners) { listener.onViewAttachedToWindow(this); } } int vis = info.mWindowVisibility; if (vis != GONE) { onWindowVisibilityChanged(vis); } if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) { // If nobody has evaluated the drawable state yet, then do it now. refreshDrawableState(); } needGlobalAttributesUpdate(false); }
1.3获得 ViewRootImpl
/** * Gets the view root associated with the View. * @return The view root, or null if none. * @hide */ public ViewRootImpl getViewRootImpl() { if (mAttachInfo != null) { return mAttachInfo.mViewRootImpl; } return null; }
1.4 View 的 dispatchPointerEvent (这个就是传进来的重点了),得到了 dispatchTouchEvent 获得 MotionEvent
public final boolean dispatchPointerEvent(MotionEvent event) { if (event.isTouchEvent()) { return dispatchTouchEvent(event); } else { return dispatchGenericMotionEvent(event); } }
1.5接下来 dispatchTouchEvent ,会陆续传给其他
public boolean dispatchTouchEvent(MotionEvent event) { if (mInputEventConsistencyVerifier != null) { //======================================================= mInputEventConsistencyVerifier.onTouchEvent(event, 0); } if (onFilterTouchEventForSecurity(event)) { //noinspection SimplifiableIfStatement ListenerInfo li = mListenerInfo; if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED && li.mOnTouchListener.onTouch(this, event)) { return true; } //========================================= if (onTouchEvent(event)) { return true; } } if (mInputEventConsistencyVerifier != null) { mInputEventConsistencyVerifier.onUnhandledEvent(event, 0); } return false; }
相关文章推荐
- codeigniter中view通过循环显示数组数据的方法
- MVVM模式中ViewModel和View、Model有什么区别?
- android开发教程之view组件添加边框示例
- Android动态添加View的问题解决方法
- android获得当前view在屏幕中坐标的方法
- Android中将View的内容保存为图像的简单实例
- Android View添加 Listener 实例代码
- Android编程之View简单学习示例
- Android中SurfaceView和view画出触摸轨迹
- Android加载View中Background详解
- Android中通过view方式获取当前Activity的屏幕截图实现方法
- BIND(二)—— dns管理,acl,forward,子域授权,view
- Android 自定义View实现画背景和前景(ViewGroup篇)
- 自定义ViewGroup (1)支持margin,gravity以及水平,垂直排列
- 自定义ViewGroup (2)支持滑动,并处理多指触摸可能产生的跳动问题
- 自定义ViewGroup (3) 与子View之间 Touch Event的拦截与处理
- 使用 yii2-detail-view 扩展修改/删除/查看模型数据
- 每周总结20130821——android控件的尺寸、http文件上传
- 玩转Android UI事件
- 封装横向滚动View