自定义控件
自定义控件
- 组合控件。这种自定义控件不需要我们自己绘制,而是使用原生控件组合成的新控件。如标题栏。
- 继承原有的控件。这种自定义控件在原生控件提供的方法外,可以自己添加一些方法。如制作圆角,圆形图片。
- 完全自定义控件:这个View上所展现的内容全部都是我们自己绘制出来的。比如说制作水波纹进度条
View的绘制流程
View的绘制流程:OnMeasure()——>OnLayout()——>OnDraw()
- OnMeasure():测量视图大小。从顶层父View到子View递归调用measure方法,measure方法又回调OnMeasure。
OnLayout():确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。
OnDraw():绘制视图。ViewRoot创建一个Canvas对象,然后调用OnDraw()。六个步骤:①、绘制视图的背景;②、保存画布的图层(Layer);③、绘制View的内容;④、绘制View子视图,如果没有就不用;⑤、还原图层(Layer);⑥、绘制滚动条。
ViewGroup的绘制流程
自定义ViewGroup可就没那么简单了,因为它不仅要管好自己的,还要兼顾它的子View。我们都知道ViewGroup是个View容器,它装纳child View并且负责把child View放入指定的位置
首先,我们得知道各个子View的大小吧,只有先知道子View的大小,我们才知道当前的ViewGroup该设置为多大去容纳它们。
根据子View的大小,以及我们的ViewGroup要实现的功能,决定出ViewGroup的大小
ViewGroup和子View的大小算出来了之后,接下来就是去摆放了吧,具体怎么去摆放呢?这得根据你定制的需求去摆放了,比如,你想让子View按照垂直顺序一个挨着一个放,或者是按照先后顺序一个叠一个去放,这是你自己决定的。
已经知道怎么去摆放还不行啊,决定了怎么摆放就是相当于把已有的空间”分割”成大大小小的空间,每个空间对应一个子View,我们接下来就是把子View对号入座了,把它们放进它们该放的地方去。
DecorView
DecorView的作用
DecoView是顶级View,本质是一个FrameLayout它包含两部分,标题栏和内容栏,都是FrameLayout。
内容栏id是content,也就是activity中设置setContentView的部分,最终将布局添加到id为content的FrameLayout中。
获取content:ViewGroup content = findViewById(android.id.content)
获取设置的View:getChildAt(0)
DecorView使用
每个Activity都包含一个Window对象,Window对象通常是由PhoneWindow实现的。
PhoneWindow:将DecorView设置为整个应用窗口的根View,是Window的实现类。它是Android中的最基本的窗口系统,每个Activity均会创建一个PhoneWindow对象,是Activity和整个View系统交互的接口。
DecorView:是顶层视图,将要显示的具体内容呈现在PhoneWindow上,DecorView是当前Activity所有View的祖先,它并不会向用户呈现任何东西。
View事件分发
View的事件分发
dispatchTouchEvent —> onTouch(setOnTouchListener) —> onTouchEvent —> onClick
onTouch和onTouchEvent的区别
onTouch和onTouchEvent的区别
两者都是在dispatchTouchEvent中调用的,onTouch优先于onTouchEvent,如果onTouch返回true,那么onTouchEvent则不执行,及onClick也不执行。
ViewGroup事件分发
ViewGroup事件分发
当一个点击事件产生后,它的传递过程将遵循如下顺序:Activity —> Window —> View
事件总是会传递给Activity,之后Activity再传递给Window,最后Window再传递给顶级的View,顶级的View在接收到事件后就会按照事件分发机制去分发事件。如果一个View的onTouchEvent返回了FALSE,那么它的父容器的onTouchEvent将会被调用,依次类推,如果所有都不处理这个事件的话,那么Activity将会处理这个事件。
对于ViewGroup的事件分发过程,大概是这样的:如果顶级的ViewGroup拦截事件即onInterceptTouchEvent返回true的话,则事件会交给ViewGroup处理,如果ViewGroup的onTouchListener被设置的话,则onTouch将会被调用,否则的话onTouchEvent将会被调用,也就是说:两者都设置的话,onTouch将会屏蔽掉onTouchEvent,在onTouchEvent中,如果设置了onClickerListener的话,那么onClick将会被调用。如果顶级ViewGroup不拦截的话,那么事件将会被传递给它所在的点击事件的子view,这时候子view的dispatchTouchEvent将会被调用
onInterceptTouchEvent作用
- 拦截Down事件的分发;
- 中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。
Surface View & View 的区别
- View的更新必须在UI thread中进行;
- Surface View会单独有一个线程做ui的更新;
- Surface View 支持open GL绘制。