天天看点

安卓View和ViewGroup简介UI绘制事件分发

简介

在安卓app的页面中,所有的界面都是由View和ViewGroup组合而成的。View其实就是绘制在屏幕上与用户交互的对象,而ViewGroup是View的子类它可以理解成是存放其他View( ViewGroup)的容器。他们的结构如图:

安卓View和ViewGroup简介UI绘制事件分发

UI绘制

绘制流程:Measure(测量)——》Layout(布局)——》Draw(绘制)

安卓View和ViewGroup简介UI绘制事件分发

onDraw用于UI重绘,onLayout则在布局发生变化时调用,onMeasure计算view对象的大小。

ps:关于过度绘制

检测:在usb调试助手中打开GPU过度绘制的调试。

内容:蓝色(一层覆盖,像素两次绘制,大片的蓝色可以接受),绿色(两层覆盖,三次绘制,中等范围可以接受但需要减少),浅红色(三层覆盖,四次绘制,小范围可以接受),深红色(四层覆盖,五次绘制或更多,为错误现象必须去修正)

优化方法:减少布局层级,去除不必要的背景(或设为透明)。

事件分发

事件U型流向:Activity---->ViewGroup—>(调用dispatchTouchEvent)View–>( 调用onTouchEvent)ViewGroup—>Activity。

当然,这是在没有重写控件(view)方法和改变返回值而是直接用super调用父类的默认实现 的情况下,即return super.xxxxx()。

而事实上,从Activity开始向下分发事件,只有返回super.dispatchTouchEvent(ev)才会往下分发到ViewGroup,否则无论返回True或False都不会再继续往下分发。

然后是ViewGroup的事件分发,ViewGroup也是只有当dispatchTouchEvent返回super.dispatchTouchEvent(ev)时才会继续向子View分发,如果返回false则向上将事件交由Activity的onTouchEvent处理,返回true则终止分发事件走到尽头,而ViewGroup自己有一个onInterceptTouchEvent方法,这个方法是用来拦截事件给自己处理的,该方法返回true就可以将事件传递到ViewGroup的onTouchEvent方法中,返回false或者super.onInterceptTouchEvent都表示不拦截继续往子View传递。

最后事件总算到达View这边,子View的dispatchTouchEvent方法和ViewGroup类似:如果返回true那么就终止事件分发,返回false则是向上交由ViewGroup处理即分发到ViewGroup的onTouchEvent中。而view没有onInterceptTouchEvent方法,所以要想自己处理该事件,则返回super.dispatchTouchEvent(ev)即可(调用super.dispatchTouchEvent默认将事件分发到自身的onTouchEvent中)。

贴出一张来自其它博客中的图,标出图中的super可以发现只要返回父类的默认实现(super.xxx()),就会一直按照先向下分发一直到某个叶子view结点才向上回溯一直到Activity的onTouchEvent方法。向下的过程中,dispatchEvent返回true事件就认为被消费,返回false会停止分发并向上回溯到父控件的onTouchEvent中;向上的过程中,onTouchEvent返回true则表示事件被消费了,返回false(或者super.onTouchEvent)则继续向上回溯。

安卓View和ViewGroup简介UI绘制事件分发

最后再总结一下事件分发的内容:首先Activity的dispatchTouchEvent返回true或false都会结束事件分发,只有返回super.dispatchTouchEvent才会将事件分发到ViewGroup的dispatchTouchEvent;对于ViewGroup的dispatchTouchEvent返回true则事件分发终止,返回false的话会向上分发到Activity的onTouchEvent,只有返回super.dispatchTouchEvent才会继续向下分发到子View的dispatchTouchEvent;不过在此之前还会有一个ViewGroup的拦截器的判断,如果onInterceptTouchEvent的返回值为true,则事件将被拦截到ViewGroup自己的onTouchEvent,除此之外无论返回false还是super.onInterceptTouchEvent都将不会拦截事件,事件会继续向子View分发;最后就是View的dispatchTouchEvent,返回true则事件终止分发认为被消费,返回false事件会向上回溯到ViewGroup的onTouchEvent中,而返回super.dispatchTouchEvent则表示自己消费该事件。