Android 控件架构
- 每个 Activity 都包含一个 Window 对象,Window 对象由 PhoneWindow 实现
- PhoneWindow 将一个 DecorView 设置为这个应用的根 View
- DecorView 作为窗口界面的顶级视图,封装了一些窗口操作的通用方法
所有的 View 监听的事件,都通过
WindowManagerService
来进行接收
- TitleView
-
ContetnView 也就是
setContentView()
里面的视图
这里的控件架构解释了 requestWindowFeature()
为何要在 setContentView()
方法之前才可以生成的原因
在代码上,当程序中 调用 setContentView()
后 ActivityManagerService
会回调 onResumen()
方法,此时系统把整个 DecorView 添加到 PhoneWindow 中,并让其显示出来,从而完成界面的绘制
View 的测量
MeasureSpec 类 ,Spec 规范
MeasureSpec :一个 32 位的 int 值
- 高 2 位 为测量的模式
- 低 30 位为测量的大小
使用位运算的原因:提高并优化效率
测量的模式:
EXACTLY(Default) | AT_MOST | UNSPECIFIED |
---|---|---|
match_parent or 精确值 | wrap_content | 想多大就多大 |
onMeasue()
默认仅支持 EXACTLY 模式,要让自定义 View 支持 AT_MOST 模式,就必须重载 onMeasue()
方法
View 的绘制
重载方法 onDraw(Canvas canvas)
方法中有一个可以操纵的 画布对象 canvas ,而实际上当需要 new 一个 canvas 时,需要传入一个 bitmap 的对象
bitmap 对象 与 canvas 对象上关联的,
bitmap 对象用来存储所有绘制在 canvas 上的像素信息。
所以操作 canvas 对象,可以理解为 canvas 对象对 bitmap 对象进行操纵。
ViewGroup 的测量
ViewGroup 可以存放 ViewGroup 和 View,竟然可以存放这些对象,就需要对这些对象进行负责,包括子View的显示大小:
-
onMeasure()
当 ViewGroup 的大小为 wrap_content(AT_MOST 模式)时,ViewGroup 便需要的子 View 进行遍历,以获取所有子 View 的大小,从而来决定自己的大小 -
onLayout()
当 子View 测量完后,需要将子 View 放到合适的位置,,这个过程就是 View 的Layout 过程,这里同样需要进行遍历。ViewGroup 在执行 Layout 过程中,同样上使用遍历来调用子 View 的 Layout 方法,并指定其具体显示的位置,从而来决定其布局位置
ViewGroup 的绘制
通常并不需要绘制
-
onDraw()
指定 ViewGroup 的背景颜色时才被调用 -
dispatch()
绘制 ViewGroup 的子 View
自定义 View
重要的回调方法:
-
onMeasure()
:进行测量 -
onLayout()
:确定显示的位置 -
onTouchEvent()
:监听触摸事件的回调 -
onFinishInflate()
:从 XML加载组件后回调 -
onSizeChanged()
:组件改变大小时回调
扩展原有控件
- 定义属性 attrs.xml
<declare-styleable name="customer_name">
<attr name = "attr_name" format="reference|dimension"/>
</declare-styleable>
2.java
TypeArray ta =context.obtainStyleAttributes(attrs,R.styleable.customer_name);
ta.rececle() //资源回收
创建复合控件
待续。。。
继承 View
待续。。
自定义 ViewGroup
-
onMeasure()
:对子 View 进行测量 -
onLayout()
:确定子 View 的位置 -
onTouchEvent()
:增加响应事件