深入一些,看下Client这边ViewTree相关原理
我们在日常开发中,会override Activity的onCreate方法,并且调用setContentView方法对页面的内容View进行设置。 而android viewTree体系的根就是在这个方法中进行建立的,我们这篇文章将说下viewTree的原理。
viewTree根结点建立
调用setContentView后,会触发一个DecorView对象的创建,DecorView对象很重要。从下面的层级图可以看到DecorView继承自FrameLayout,并且添加到window对象上,是android视图所有view的根节点。我们调用setContentView设置的view,都添加到android.R.id.content这个节点下,使用View和ViewGroup组合的方式构建出一个视图树
View ViewGroup
从类结构来说,View是ViewGroup的父类,ViewGroup的定位是View的容器,在设计模式上属于组合模式.measure layout draw的调用,都是从根节点开始,用后序的方式进行遍历计算。其中某个节点的数据有变化,会引起父节点和相关联节点的重绘。
整体事件
ViewRootImpl接到系统传来的事件后,以消息的方式(handler(MainLooper))通知到activity。activity再从DecorView开始遍历ViewTree,对事件进行分发和消费。具体如下:
-
事件产生:当用户在触摸屏幕上进行操作时,例如点击、滑动或长按,Android 系统会将这些操作转化为相应的事件。
-
事件分发:事件分发是指将产生的事件传递给正确的 View 进行处理。在 Android 中,事件分发是基于视图层级结构进行的。事件从根 View(通常是 Activity 的根布局)开始,逐级向下传递,直到找到合适的目标 View 来处理事件。
-
分发顺序:事件首先传递给根 View,然后通过 View 的 dispatchTouchEvent()方法逐级向下传递给子 View,直到找到目标 View 或事件被消费。
-
事件分发过程中会依次触发三个关键方法:
- dispatchTouchEvent():负责事件的分发,决定事件的传递方向。
- onInterceptTouchEvent():用于拦截事件,即判断是否将事件截获并交由自身处理。
- onTouchEvent():用于处理事件,执行具体的逻辑操作。
-
事件处理:一旦目标 View 被确定,事件就会传递给该 View 的 onTouchEvent()方法进行处理。在 onTouchEvent()方法中,开发者可以根据事件类型(例如点击、滑动、长按等)执行相应的操作。事件的处理结果可能会影响后续事件的传递。
-
事件传递结束:事件传递会一直沿着 View 层级向下传递,直到事件被消费或到达最底层的 View。如果事件在某个 View 上被消费(即被处理),则事件传递结束。否则,事件会继续向上传递给父级 View 进行处理。
需要注意的是,事件的传递是根据 View 层级结构和触摸事件的性质决定的。View 可以设置监听器来处理特定的事件,也可以重写相关的事件处理方法来实现自定义的事件处理逻辑。此外,Android 还提供了一些特殊的事件类型,例如手势(Gesture)事件、滚动(Scroll)事件等。这些事件可以通过特定的监听器或手势识别器来处理。
事件主要包括点按、长按、拖拽、滑动等,点按又包括单击和双击,另外还包括单指操作和多指操作,这些都构成了 Android 中的事件响应。事件即 MotionEvent,继承于 InputEvent,用于标记各种动作事件。其中比较重要的有以下三个:
- MotionEvent.ACTION_DOWN:按下 View,是所有事件的开始。
- MotionEvent.ACTION_MOVE:滑动事件。
- MotionEvent.ACTION_UP:与 down 对应,表示抬起。
View 的坐标体系原点在屏幕左上角,View 常用属性有 mTouchSlop(系统能识别的被认为是滑动的最小距离)、VelocityTracker(速度追踪)和 GestureDetector(手势检测)。处理滑动时,用 mTouchSlop 常量过滤未达到临界值的移动行为。VelocityTracker 用于追踪手指滑动的速度,包括水平和竖直方向的速度。GestureDetector 用于辅助检测用户的单击、滑动、长按、双击等行为。