RoundedLetterView源码深度解析:onMeasure与onDraw如何画出完美圆形字母头像
RoundedLetterView源码深度解析onMeasure与onDraw如何画出完美圆形字母头像【免费下载链接】RoundedLetterViewRoundedLetterView like the one in Android 5.0 Contacts app项目地址: https://gitcode.com/gh_mirrors/ro/RoundedLetterViewRoundedLetterView 是一个轻量级 Android 自定义 View 控件它能像 Android 5.0 通讯录那样画出带 A、B、C 字母的彩色圆形头像——这正是联系人应用里没有照片就用首字母的经典样式。整个库的核心逻辑只有不到 200 行 Java 代码全部集中在 RoundedLetterView.java 这一个文件里。本文带你逐行拆解它的onMeasure和onDraw两大方法看懂一个永远完美居中、永远正圆的字母头像是如何画出来的。效果预览通讯录里的圆形字母头像长什么样先来看运行效果一个列表里每个联系人左侧都有一个彩色正圆圆内是白色首字母绿色和红色交替出现——这就是 RoundedLetterView 的目标样式项目结构核心代码藏在哪里 项目结构非常简洁整个控件就是一个 Android Library 模块文件作用roundedletterview/src/main/java/com/github/pavlospt/roundedletterview/RoundedLetterView.java控件主体全部绘制逻辑roundedletterview/src/main/res/values/attrs_rounded_letter_view.xml4 个 XML 自定义属性声明roundedletterview/build.gradle模块配置minSdk 19版本 1.3也就是说读懂RoundedLetterView.java这一个文件就读懂了整个库。onMeasure 深度解析为什么它永远是正圆打开源码onMeasure只有关键的几行第 93-102 行先用resolveSize从布局的 MeasureSpec 中解析出宽高如果布局写的是wrap_content就回退到默认值DEFAULT_VIEW_SIZE 96dp 级像素然后做最关键的一步mViewSize Math.min(width, height)。精髓就在这句Math.min当控件被拉成长方形比如宽 200、高 100时mViewSize取较短的边 100圆形始终按短边绘制配合后面的居中偏移圆形就不会被拉伸成椭圆最后setMeasuredDimension(width, height)保留控件本身的外接矩形尺寸圆只是画在矩形中间。 新手提示自定义 View 想画圆最经典的坑就是宽高等比失真。Math.min(width, height) 居中偏移是解决这个问题的标准套路。onDraw 深度解析两行代码一个圆 一个字母onDraw第 104-122 行的绘制步骤可以拆成 4 步确定圆形区域mInnerRectF.set(0, 0, mViewSize, mViewSize)先画一个从原点出发、边长为mViewSize的正方形区域——这是圆的内切正方形整体居中偏移mInnerRectF.offset((getWidth() - mViewSize) / 2, (getHeight() - mViewSize) / 2)把圆平移到控件正中央。宽为高为正方形时偏移量为 0圆自然占满宽大于高时圆就垂直居中画圆canvas.drawOval(mInnerRectF, mBackgroundPaint)用填充模式Paint.Style.FILL 抗锯齿把内切正方形画成一个实心圆写字canvas.drawText(...)在圆心位置画出字母。背景 Paint 只配置了抗锯齿、填充样式和颜色文字用TextPaintsetTextAlign(Paint.Align.CENTER)让文字水平方向自动以 x 坐标为中心——水平居中就这样解决了。文字垂直居中的技巧ascent 与 descent ✍️水平居中靠Align.CENTER那垂直方向呢源码第 114 行藏着一个非常经典的手势yPos centerY - (mTitleTextPaint.descent() mTitleTextPaint.ascent()) / 2ascent()返回的是负值基线到文字顶部的距离descent()是正值基线到文字底部两者相加正好得到文字在基线上下占据的视觉总高度用圆心 y 减去它的一半就把文字从基线对齐修正为视觉垂直居中。如果直接把centerY当作 y 传入drawText字母会偏上一点——因为drawText的 y 指的是基线而不是文字中心。这一步是很多自定义 View 教程里最容易被忽略的细节。4 个 XML 属性不写一行 Java 也能配置外观属性声明在roundedletterview/src/main/res/values/attrs_rounded_letter_view.xml共 4 个全部带rlv_前缀属性含义默认值rlv_titleText圆内显示的字母Arlv_titleSize字母字号25dprlv_titleColor字母颜色白色rlv_backgroundColorValue圆形背景色青色构造函数里通过obtainStyledAttributes一次性读取这 4 个属性读不到就用默认值。运行时还能用setTitleText、setBackgroundColor、setTextTypeface等方法动态修改——每个 setter 内部都会调用invalidate()触发重绘这也是自定义 View 响应状态变化的标准写法。如何集成到你的项目 仓库地址https://gitcode.com/gh_mirrors/ro/RoundedLetterView克隆后将roundedletterview模块作为 Library 依赖引入或在布局中直接声明控件android:layout_width/android:layout_height建议写成正方形如 56dp圆会自动占满通过上面 4 个rlv_属性定制字母、颜色、字号字母文本一般取联系人名字的首字母循环切换rlv_backgroundColorValue即可复现截图中的红绿交替效果。总结自定义 View 画圆的 3 个要点 onMeasure里用Math.min锁定短边保证圆形不被拉伸变形onDraw里用内切正方形 drawOval画圆宽度过剩时用 offset 居中文字垂直居中要减去(ascent descent) / 2水平居中交给Align.CENTER。RoundedLetterView 用不到 200 行代码把这三件事做对了就是你在通讯录 App 里看到的那个完美圆形字母头像的全部秘密。把这个模式记住之后画任何圆形图标、头像占位符都能举一反三。【免费下载链接】RoundedLetterViewRoundedLetterView like the one in Android 5.0 Contacts app项目地址: https://gitcode.com/gh_mirrors/ro/RoundedLetterView创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考