第3章 View体系与自定义View

依据2017年首版完整目录覆盖29个节点:贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View

第3章 View体系与自定义View

在《第3章 View体系与自定义View》中,本页依据刘望舒《Android进阶之光》独立重构,不复制原文。版本锁定电子工业出版社2017年7月首版、492页、ISBN 9787121315305;正式结构为11章、190个章/节/小节节点。

在《第3章 View体系与自定义View》中,原书处在Android 5.0至7.0、Java与Support Library时代,包含AsyncTask、Volley、otto、RxJava早期版本、ButterKnife、Dagger 2和Data Binding。课程先复现历史机制,再以AndroidX、协程/Flow、现代架构组件作迁移对照。

学习目标

  • 能解释“第3章 View体系与自定义View”全部29个正式节点的输入、线程、生命周期与可观察结果。
  • 能实现“贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View”的最小可运行切片并保存版本、源码、样本和日志。
  • 能区分正确结果、框架便利、隐藏成本和版本差异,并用MotionEvent序列、坐标换算、MeasureSpec、测量尺寸、布局坐标、绘制边界与父子拦截日志验收。
  • 能设计反例推翻“只让自定义View在固定尺寸下看起来正确,不处理测量模式、padding、事件冲突和状态恢复”,写出2017年机制到现代Android的迁移与回退条件。

机制总览

第3章 View体系与自定义View:机制路径

  1. 1

    从可观察行为开始

    本单元主线是贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View。交互管线逐项选择目录节点,反例实验切换正常、配置变化、线程竞争、所有者销毁和版本漂移,证据门要求目录、行为、线程、生命周期与迁移全部通过。

  2. 2

    最小实现与边界

    在《第3章 View体系与自定义View》中,实现后用固定输入记录输出、线程名、生命周期、异常和资源释放。再构造错误输入、取消、旋转、后台切前台及低版本设备,验证便利框架没有隐藏所有权问题。

  3. 3

    证据解释

    第一份证据是行为基线。固定Android版本、依赖版本、构建类型、输入数据和页面生命周期,完整记录“贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View”从入口到结果的顺序。除了成功输出,还要保存回调线程、对象身份、队列或订阅状…

先按顺序建立机制,再进入实验切换阶段并检查失效证据。

章级决策实验

第3章 View体系与自定义View:机制与证据

切换《第3章 View体系与自定义View》的三个关键教学阶段,先解释机制,再用运行与失败证据验证结论。

选择推理阶段

当前阶段 · 从可观察行为开始

本单元主线是贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View。交互管线逐项选择目录节点,反例实验切换正常、配置变化、线程竞争、所有者销毁和版本漂移,证据门要求目录、行为、线程、生命周期与迁移全部通过。

可核验证据

在固定 Android 5–7 基线运行「从可观察行为开始」的正常与单变量失败样本,保存回调线程、状态快照、资源释放和 AndroidX/现代 API 迁移对照。

学完《第3章 View体系与自定义View》后,应能从输入和前置条件推导状态变化,并用可重复的构建、运行或边界测试证明结果。

失效—证据矩阵

第3章 View体系与自定义View:失效与核验

从可观察行为开始

典型失效

若把「从可观察行为开始」只写成旧框架 API 示例而不说明线程、生命周期、状态所有者与现代迁移边界,正常演示会在取消、重建或版本升级后失效。

核验证据

在固定 Android 5–7 基线运行「从可观察行为开始」的正常与单变量失败样本,保存回调线程、状态快照、资源释放和 AndroidX/现代 API 迁移对照。

最小实现与边界

典型失效

若把「最小实现与边界」只写成旧框架 API 示例而不说明线程、生命周期、状态所有者与现代迁移边界,正常演示会在取消、重建或版本升级后失效。

核验证据

在固定 Android 5–7 基线运行「最小实现与边界」的正常与单变量失败样本,保存回调线程、状态快照、资源释放和 AndroidX/现代 API 迁移对照。

证据解释

典型失效

若把「证据解释」只写成旧框架 API 示例而不说明线程、生命周期、状态所有者与现代迁移边界,正常演示会在取消、重建或版本升级后失效。

核验证据

在固定 Android 5–7 基线运行「证据解释」的正常与单变量失败样本,保存回调线程、状态快照、资源释放和 AndroidX/现代 API 迁移对照。

每个判断都必须能落到观测、测试或产物,不能只凭代码表面推测。

从可观察行为开始

构成本页的分析词汇。先预测一次输入会穿过哪些对象、线程、队列、View或语言边界,再运行正常与失败样本;没有版本和原始证据的“源码原理”不能复查。

本单元主线是贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View。交互管线逐项选择目录节点,反例实验切换正常、配置变化、线程竞争、所有者销毁和版本漂移,证据门要求目录、行为、线程、生命周期与迁移全部通过。

最小实现与边界

override fun onMeasure(widthSpec: Int, heightSpec: Int) {
    val desiredWidth = contentWidth + paddingLeft + paddingRight
    val desiredHeight = contentHeight + paddingTop + paddingBottom
    setMeasuredDimension(
        resolveSize(desiredWidth, widthSpec),
        resolveSize(desiredHeight, heightSpec)
    )
}

在《第3章 View体系与自定义View》中,实现后用固定输入记录输出、线程名、生命周期、异常和资源释放。再构造错误输入、取消、旋转、后台切前台及低版本设备,验证便利框架没有隐藏所有权问题。

data class AndroidProbe(
    val apiLevel: Int,
    val ownerActive: Boolean,
    val callbackThread: String,
    val resultStable: Boolean
)
check(probe.ownerActive && probe.resultStable)

证据解释

第一份证据是行为基线。固定Android版本、依赖版本、构建类型、输入数据和页面生命周期,完整记录“贯通坐标、六种滑动方式、属性动画、Scroller、事件分发、measure/layout/draw流程和四类自定义View”从入口到结果的顺序。除了成功输出,还要保存回调线程、对象身份、队列或订阅状态以及释放日志;否则无法判断升级后的差异来自业务代码、框架实现还是测试环境。

第二份证据是反例。针对“只让自定义View在固定尺寸下看起来正确,不处理测量模式、padding、事件冲突和状态恢复”构造至少一个可重复失败:在配置变化、快速重复输入、网络超时、后台切换或所有者销毁时观察错位、重复、泄漏和迟到回调。反例必须写明预期拒绝条件;只展示正常路径会掩盖框架最重要的所有权边界。

第三份证据是源码定位。先锁定仓库标签和库版本,再从公开入口沿实际调用追踪,不跨版本拼接类名。每次跨线程、跨进程或跨Java/Native边界,都记录调用方、被调用方、数据形态、错误返回和资源归属。MotionEvent序列、坐标换算、MeasureSpec、测量尺寸、布局坐标、绘制边界与父子拦截日志应能让另一位读者在相同版本上重建同一条链。

在《第3章 View体系与自定义View》中,第四份证据是迁移对照。现代API解决的问题可能相同,但取消、缓存、状态恢复、线程和错误语义未必一致。迁移时保持输入和验收不变,一次只替换一个组件;新旧结果不一致时先解释差异,再决定适配或回退,不能用“新版推荐”跳过历史行为验证。

迁移账本

原书节点: 第3章 View体系与自定义View
历史基线: Android 5.0—7.0 / Java / Support Library
现代候选: 一次只替换一个API或框架
不变量: 业务结果、线程、生命周期、错误与资源释放
证据: MotionEvent序列、坐标换算、MeasureSpec、测量尺寸、布局坐标、绘制边界与父子拦截日志
回退: 任一不变量失败即恢复历史实现

本章回顾

从一个真实输入复盘:它由谁接收、在哪个线程执行、状态和对象归谁所有、何时取消或释放、低版本与异常路径如何表现。然后用MotionEvent序列、坐标换算、MeasureSpec、测量尺寸、布局坐标、绘制边界与父子拦截日志重放;无法复现的结论退回实验阶段。

复习与独立交接

练习

问题 1:为什么本页必须保留29个目录节点?

问题 2:最小正确性合同是什么?

问题 3:怎样构造最有效的反例?

问题 4:为什么只读源码类名不够?

问题 5:怎样迁移而不改写原书?

问题 6:独立交接需要什么?

名词解释

本章出现的专业名词,用大白话再讲一遍。

MeasureSpec

由尺寸值和测量模式编码而成、父View传给子View的测量要求。

事件分发

MotionEvent在Activity、ViewGroup与View之间分发、拦截和消费的协议。

Scroller

根据时间计算滚动偏移但不直接移动View的数值辅助器。

属性动画

随时间修改对象属性并通过更新回调驱动界面变化的动画体系。

自定义ViewGroup

负责测量子项并按自定义规则放置它们的复合容器。

← 上一页:第2章 Material Design · 下一页:第4章 多线程编程 →

原版目录概念补充核对

以下条目补齐官方目录中容易被示例主线掩盖的概念。它们不重复罗列目录,而是明确每项概念的机制、适用边界和验收证据。

3.1 View与ViewGroup:机制、边界与证据

第3章 View体系与自定义View中的3.1 View与ViewGroup要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.2 坐标系:机制、边界与证据

第3章 View体系与自定义View中的3.2 坐标系应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.2.1 Android坐标系:机制、边界与证据

第3章 View体系与自定义View中的3.2.1 Android坐标系应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.2.2 View坐标系:机制、边界与证据

第3章 View体系与自定义View中的3.2.2 View坐标系要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.3 View的滑动:机制、边界与证据

第3章 View体系与自定义View中的3.3 View的滑动要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.3.1 layout()方法:机制、边界与证据

第3章 View体系与自定义View中的3.3.1 layout()方法应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.3.2 offsetLeftAndRight()与offsetTopAndBottom():机制、边界与证据

第3章 View体系与自定义View中的3.3.2 offsetLeftAndRight()与offsetTopAndBottom()只有在参与者、状态所有者与变化点明确时才是设计机制,而不是类名套用。以最小对象图记录事件注册/注销、调用方向和替换点,再用重复注册、缺失订阅者或生命周期结束样本检验耦合与泄漏。

3.3.3 LayoutParams(改变布局参数):机制、边界与证据

第3章 View体系与自定义View中的3.3.3 LayoutParams(改变布局参数)要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.3.4 动画:机制、边界与证据

第3章 View体系与自定义View中的3.3.4 动画要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.3.5 scrollTo与scrollBy:机制、边界与证据

第3章 View体系与自定义View中的3.3.5 scrollTo与scrollBy应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.3.6 Scroller:机制、边界与证据

第3章 View体系与自定义View中的3.3.6 Scroller应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.4 属性动画:机制、边界与证据

第3章 View体系与自定义View中的3.4 属性动画要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.5 解析Scroller:机制、边界与证据

第3章 View体系与自定义View中的3.5 解析Scroller应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.6 View的事件分发机制:机制、边界与证据

第3章 View体系与自定义View中的3.6 View的事件分发机制要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.6.1 源码解析Activity的构成:机制、边界与证据

第3章 View体系与自定义View中的3.6.1 源码解析Activity的构成应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.6.2 源码解析View的事件分发机制:机制、边界与证据

第3章 View体系与自定义View中的3.6.2 源码解析View的事件分发机制要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.7 View的工作流程:机制、边界与证据

第3章 View体系与自定义View中的3.7 View的工作流程要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.7.1 View的工作流程入口:机制、边界与证据

第3章 View体系与自定义View中的3.7.1 View的工作流程入口要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.7.2 理解MeasureSpec:机制、边界与证据

第3章 View体系与自定义View中的3.7.2 理解MeasureSpec应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

3.7.3 View的measure流程:机制、边界与证据

第3章 View体系与自定义View中的3.7.3 View的measure流程要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.7.4 View的layout流程:机制、边界与证据

第3章 View体系与自定义View中的3.7.4 View的layout流程要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.7.5 View的draw流程:机制、边界与证据

第3章 View体系与自定义View中的3.7.5 View的draw流程要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.8 自定义View:机制、边界与证据

第3章 View体系与自定义View中的3.8 自定义View要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.8.1 继承系统控件的自定义View:机制、边界与证据

第3章 View体系与自定义View中的3.8.1 继承系统控件的自定义View要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.8.2 继承View的自定义View:机制、边界与证据

第3章 View体系与自定义View中的3.8.2 继承View的自定义View要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.8.3 自定义组合控件:机制、边界与证据

第3章 View体系与自定义View中的3.8.3 自定义组合控件要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.8.4 自定义ViewGroup:机制、边界与证据

第3章 View体系与自定义View中的3.8.4 自定义ViewGroup要沿输入事件、测量、布局、绘制与帧提交说明可见结果,样式名称不能代替运行机制。固定设备和界面状态后,改变一个尺寸、触摸序列或过度绘制条件,保存层级、回调顺序与帧时间验证。

3.9 本章小结:机制、边界与证据

第3章 View体系与自定义View中的3.9 本章小结应固定 Android 5.0–7.0、Java 与旧 Support Library 语境,写出输入、状态、线程、生命周期和失败结果。以最小实现和单变量反例保存日志、状态快照与迁移差异。

资料与写作方式声明

本章以刘望舒《Android进阶之光》权威目录界定学习范围,并结合正文列出的技术资料独立重写;不宣称复现原书正文,也不沿用原作表述。

原作版权归作者与出版社所有;本站原创教学结构与表述仅供学习交流。

讨论

评论区加载中…