发布时间:2026/8/16 1:20:41
android 自定义view 详解(二) 一、View 绘制流程1. View 的绘制流程是什么measure/layout/draw 分别做什么measure测量 View 的宽高从根 View 递归调用measure()→onMeasure()结果存在mMeasuredWidth/Heightlayout确定 View 的位置调用layout()→onLayout()子 View 一般在这里调用child.layout()draw绘制内容调用draw()→ 依次执行drawBackground→onDraw→dispatchDraw→onDrawForeground2. MeasureSpec 是什么三种模式有什么区别模式值含义EXACTLY1精确值如match_parent或具体数值AT_MOST2最大值如wrap_contentUNSPECIFIED0无限制如 ScrollView 中的子 View3. 为什么onMeasure会执行多次父 View 可能多次测量子 View 以确定最终尺寸典型的如RelativeLayout、LinearLayout的权重分配4.getWidth()和getMeasuredWidth()的区别getMeasuredWidth()measure 阶段获取的原始测量值getWidth()layout 阶段确定的最终宽度mRight - mLeft通常两者相等但在某些自定义布局中可能不同二、自定义 View 的分类与选择5. 自定义 View 有哪些实现方式如何选择方式适用场景特点继承 View完全自定义绘制重写onDraw无子 View继承 ViewGroup自定义布局重写onLayout管理子 View 位置继承已有 View扩展功能如继承 TextView 增加新属性继承已有 ViewGroup组合控件如继承 FrameLayout 封装复杂 UI6. 自定义 View 如何支持wrap_content必须在onMeasure中处理AT_MOST模式否则wrap_content效果等同于match_parent示例javaif (widthMode MeasureSpec.AT_MOST) { widthSize desiredWidth; }三、触摸事件分发高频考点7. 事件分发的三个核心方法dispatchTouchEvent分发事件返回 true 表示消费onInterceptTouchEventViewGroup 专属是否拦截事件onTouchEvent处理事件8. 事件传递顺序plainActivity.dispatchTouchEvent → PhoneWindow.DecorView.dispatchTouchEvent → ViewGroup.dispatchTouchEvent → onInterceptTouchEvent返回 true 则拦截调用自己的 onTouchEvent → 不拦截则传给子 View → 子 View 的 dispatchTouchEvent → onTouchEvent9. 如果子 View 不消费事件事件会怎么处理子 View 的onTouchEvent返回 false → 事件回传给父 View 的onTouchEvent如果所有 View 都不消费最终回传给 Activity 的onTouchEvent10.requestDisallowInterceptTouchEvent的作用子 View 调用此方法可以阻止父 View 拦截事件常用于解决 ScrollView 嵌套 RecyclerView 的滑动冲突四、自定义绘制11.onDraw中常用的 Canvas API 有哪些绘制基础图形drawLine、drawRect、drawCircle、drawOval、drawArc绘制文字drawText绘制路径drawPath绘制图片drawBitmap12. Paint 常用属性setColor/setARGB颜色setStrokeWidth描边宽度setStyleFILL填充、STROKE描边、FILL_AND_STROKEsetAntiAlias抗锯齿setTextSize文字大小13. Path 的使用场景绘制贝塞尔曲线、复杂形状moveTo、lineTo、quadTo二阶贝塞尔、cubicTo三阶贝塞尔addArc、addCircle等添加基本图形14.Canvas.save()和Canvas.restore()的作用save()保存当前 Canvas 状态坐标系、裁剪区域等restore()恢复到上一次 save 的状态常用于临时变换坐标系后恢复五、动画15. Android 动画的分类类型实现方式特点补间动画View AnimationAlphaAnimation、TranslateAnimation等只改变视觉效果不改变实际属性属性动画Property AnimationValueAnimator、ObjectAnimator真正改变属性值更灵活帧动画Drawable AnimationAnimationDrawable逐帧播放图片16. 属性动画的原理通过ValueAnimator在时间内计算插值利用反射或setter方法不断更新目标属性底层依赖Choreographer的VSync信号驱动17. 自定义 View 中如何实现属性动画定义属性对应的setter方法使用ObjectAnimator.ofFloat(view, propertyName, values...)或者使用ValueAnimatorAnimatorUpdateListener手动更新六、性能优化18. 自定义 View 有哪些性能优化手段避免在onDraw中创建对象应提前初始化 Paint、Path 等使用clipRect和quickReject减少不必要的绘制区域开启硬件加速setLayerType(View.LAYER_TYPE_HARDWARE, null)使用invalidate(Rect)局部刷新而非全屏刷新避免过度绘制减少重叠区域的绘制次数19. 什么是双缓冲自定义 View 中如何利用双缓冲在内存中先绘制到 Bitmap再一次性绘制到屏幕自定义 View 中可通过setLayerType或手动使用离屏 Bitmap 实现20.invalidate()和requestLayout()的区别invalidate()触发重绘调用onDraw不改变尺寸requestLayout()触发重新测量和布局调用onMeasure→onLayout七、其他细节问题21. 自定义属性attrs如何定义和使用在res/values/attrs.xml中定义declare-styleable在构造方法中通过TypedArray获取属性值记得typedArray.recycle()回收22. 自定义 View 的三个构造方法分别什么时候调用一参代码中new View(context)二参XML 中使用三参XML 中使用 指定 style四参API 21XML 中使用 指定 theme attribute23.postInvalidate()和invalidate()的区别invalidate()必须在 UI 线程调用postInvalidate()内部通过 Handler 投递到 UI 线程可在子线程调用24. 如何解决自定义 View 的内存泄漏及时移除动画监听和 Handler 回调避免在onDraw中创建大量临时对象页面销毁时停止动画八、实战场景题25. 如何实现一个圆形进度条思路继承 View在onDraw中用drawArc绘制背景圆弧和进度圆弧通过属性动画更新进度值调用invalidate重绘26. 如何实现一个可拖拽的 View在onTouchEvent中处理ACTION_DOWN、ACTION_MOVE、ACTION_UPACTION_MOVE时计算偏移量调用layout()或offsetLeftAndRight()更新位置或使用ViewDragHelper更推荐27. 如何实现一个折线图/柱状图计算坐标映射关系使用Path连接数据点考虑边缘 padding、动画过渡效果

相关新闻

2026/8/16 1:15:40

3.Qt中容器类型的控件

1. QWidget关于QWidget在前面的章节中已经介绍过了, 这个类是所有窗口类的父类, 可以作为独立窗口使用, 也可以内嵌到其它窗口中使用。Qt中的所有控件都属于窗口类, 因此这个类也是所有控件类的基类。如果一个窗口中还有子窗口, 为了让子窗口有序排列&am…

2026/8/16 1:15:40

Python断点调试终极指南

于其中设置断点的办法存有多种, 涵盖运用pdb模块, 包含集成开发环境也即IDE像或的断点功能, 以及借助代码里的调试语句 以下是其中一种办法的详尽描述:采用pdb模块乃是最为根本且最为灵动的方式, 能于代码里插入pdb; pdb.(), 此情形会在程序运行至该行之际暂停执行, 进而步入交…

2026/8/16 1:15:40

Python查map()用法?按住Ctrl点一下,瞬间惊呆

讲解高阶函数 map() 的具体应用方式。1、 在中创建一个新文件。2、 于输入map( )之后, 按住Ctrl这个按键继而点击map, 能够查看内置模块, 会发觉map( )事实上是某类, 并且其名称的首字母是小写的, 不合乎通常拟定名称的习惯。3、 有众多类包含于内置模块之中, 像常见的 int() 呀…

2026/8/16 2:31:10

用AI自动生成pandas代码:自然语言转Python数据分析师

前言 如果你每天都在用pandas做数据分析,你大概也经历过这样的场景:明明知道自己想做什么操作,却记不清具体的API语法,于是在文档里翻来翻去。 “是.agg()传字典还是传列表?”“滚动平均是.rolling()然后.mean()吗&a…

2026/8/16 2:31:10

分页查询的基石:ArkTS 为鸿蒙商品列表设计 LIMIT/OFFSET 的表

实例:商品分页列表(Product)|技术:商品字段、批量种子生成、ProductDao一、业务需求分析:当数据量变大,列表需要分页 前面的实例里,列表都是「一次加载全部」——几十条数据毫秒级加…

2026/8/16 2:31:10

计算机网络入门:从微信聊天看懂硬件、软件、协议与数据

Lesson 2 计算机网络的组成 先看一个生活例子 假设你现在打开微信,给朋友发一句:“晚上一起吃饭。”你按下发送键以后,这句话是怎么到你朋友手机里的? 它大概会经历这样一个过程: 你的手机│▼ 家里的 WiFi&#xff08…

2026/8/16 2:31:10

GBase 8a MPP数据库单机部署实战:从环境准备到服务验证

1. 项目概述最近在帮一个做数据分析的朋友搭建测试环境,他那边有个项目需要用到国产的分析型数据库,点名要GBase 8a。说实话,虽然之前接触过不少数据库,但GBase 8a这种大规模并行处理(MPC)架构的数据库&…

2026/8/16 2:26:10

50元预算实现专业级AI音频降噪方案

1. 项目概述:低成本AI降噪方案的价值与定位作为一名长期关注音频处理技术的从业者,我深刻理解学生群体在专业学习中对降噪工具的需求与预算限制之间的矛盾。市面上主流AI降噪软件如Adobe Audition、iZotope RX动辄上千元的年费订阅,而专业录音…

2026/8/16 0:00:35

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:36

工业传感器与变送器详解:序章 从物理世界到工业数据

序章 从物理世界到工业数据 ——重新认识工业传感器与变送器 工业自动化系统正变得日益复杂。今天的工业现场早已不是简单的控制回路,而是由多层技术共同构成的立体体系:PLC、DCS、SCADA、MES、工业互联网、边缘计算与人工智能。控制系统可以执行复杂算法,工业网络可以实现…

2026/8/16 0:00:35

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:36

工业传感器与变送器详解:序章 从物理世界到工业数据

序章 从物理世界到工业数据 ——重新认识工业传感器与变送器 工业自动化系统正变得日益复杂。今天的工业现场早已不是简单的控制回路,而是由多层技术共同构成的立体体系:PLC、DCS、SCADA、MES、工业互联网、边缘计算与人工智能。控制系统可以执行复杂算法,工业网络可以实现…

2026/8/15 9:46:39

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/15 4:56:16

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/15 9:46:30

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…