• View 自定义 - 概览


    一、体系

    详见:Activity、Window、DecorView、ViewRoot 之间的关系

    二、绘制前的准备 DecorView

    详见:DecorView

    顶部图中可以看出 ViewRoot 最后一步是绘制,在绘制之前系统会有一些准备,即前面几个步骤:创建PhoneWindow、DecorView、ViewRootmpl。

    三、View类中的方法

    详见:View类中的方法

    构造

    View(context)

    单参构造:代码中 new 创建实例的时候调用。

    View(context, attrs)

    双参构造:xml中使用时调用(xml转java代码的时候反射),attrs是xml中的属性。

    View(context, attrs, defStyleAttr)

    三参构造:使用主题Style的时候调用。
    绘制过程

    onFinishInflate()

    当View和他的所有子控件被XML布局文件填充完成时被调用。

    onMeasure()

    当测量View和它的子View的尺寸需求时被调用。

    onLayout()

    当View给他的子View分配大小和位置的时候调用。

    onSizeChanged()

    当view尺寸发生变化时调用。
    事件处理

    onKeyDown()

    按下按键时调用。

    onKeyUp()

    抬起按键时调用。

    onTouchEvent()

    触摸屏幕时调用。
    焦点

    onFocusChanged()

    获取到或者失去焦点时调用。

    onWindowFocusChanged()

    窗口获取或者失去焦点时调用。
    attach

    onAttachedToWindow()

    当View被连接到一个窗口时调用。

    onDetachedFromWindow()

    当View从窗口分离时调用。

    onWindowVisibilityChanged()

    当View的窗口的可见性发生改变时调用。

    四、自定义控件的不同方式

    详见:不同实现方式

    复用已有控件复用布局文件
    组合现有的控件
    扩展已有的控件继承特定的View(如TextView)
    继承特定的ViewGroup(如LinearLayout)
    完全自定义直接继承 View主要是实现 onMeasure() + onDraw(),因为没有子元素需要布局。
    需要自己实现 wrap_content、padding,不需要自己实现 margin 该属性是由父容器决定的。
    直接继承 ViewGroup主要是实现 onMeasure() + onLayout(),因为子元素都绘制好了父容器不需要额外绘制。
    需要自己实现 wrap_content、padding、margin。

    五、绘制流程

    从 DecorView 中可以看出 View 的绘制流程开始于ViewRootImpl 对象的 performTraversals(),从视图树根节点(即 DecorView 它是个 ViewGroup)开始由上向下遍历测绘(DecorView→中间层ViewGroup→最底层View)。 

    七、自定义流程

    构造函数只执行一次,而 onMeasure()、onLayout()、onDraw() 随着控件的刷新可能会执行很多次,因此用到的对象(如 Paint)需要定义成全局变量(避免频繁创建销毁造成内存抖动),在生命周期方法中使用前需要重置(避免每次执行都拿到用过的数据)。

    7.1 重写构造自定义属性

    详见:属性 Attribute

    在 xml 中为控件设置的属性。

    • 自定义属性名称如果使用系统已定义的,例如 textSize 会在编译时报错。

    7.2 重写测量、布局、绘制

    自定义 View 主要是实现 onMeasure() + onDraw(),因为没有子元素需要布局。自定义 ViewGroup 主要是实现 onMeasure() + onLayout(),因为子元素都绘制好了父容器不需要额外绘制。 

    Measure 过程测量控件的宽高performMeasure() → measure() → onMeasure() → 子控件的 Measure 过程。
    Layout 过程

    确定控件最终宽高在父容器中的位置

    (即四个顶点位置)

    performLayout() → layout() → onLayout() → 子控件的 Layout 过程。
    Draw 过程将控件绘制在屏幕上performDraw() → draw() → onDraw() → 子控件的 Draw 过程。

  • 相关阅读:
    python经典百题之字符串长度
    [题]:排列数字 #深搜 #DFS
    我在玛莎拉蒂的广告上,加了9个特效后,科技感拉满!
    R语言ggplot2可视化:ggcharts包的bar_chart函数可视化条形图、bar_chart函数自动排序条形图并水平显示
    HIVE中的常用和不常用的函数总结及hive中的常见问题(自用)
    JVM-内存模型(运行时数据区)
    计算机网络网络层、应用层、数据链路层协议详解
    nginx详细升级步骤
    IntelliJ IDEA远程调试:使用IDEA Remote Debug进行高效调试的指南
    Codeforces Round 928 (Div. 4) (A-E)
  • 原文地址:https://blog.csdn.net/HugMua/article/details/133928076