96SEO 2026-06-07 12:22 0
前言:聊聊为什么要自定义 Drawable 实现圆角玻璃背景
说实话,Android 原生的 shape、layer‑list 那套玩意儿Yi经够用了。
但是当你想要那种 iOS 那种毛玻璃模糊、边缘带点光晕的炫酷效果时普通 XML 就显得力不从心。

哈哈,这时候自定义 Drawable 上场了。
它不仅Neng随时改颜色、圆角半径,还Neng直接当 background 给任何 View 用,简直是神器。
准备工作:先弄清楚 Drawable 的核心方法自定义 Drawable 必须覆写几个关键函数:
draw —— 真正绘制的地方。
setAlpha、setColorFilter —— 控制透明度和颜色过滤。
getOpacity —— 告诉系统你的透明度类型。
onBoundsChange —— 当 View 大小变化时会回调,你Ke以在这里算出圆角半径和矩形区域。
别忘了还有两个可选的 getIntrinsicWidth/Height,用来支持 wrap_content 场景。
一步步实现「玻璃」效果的圆角 Drawable 1️⃣ 定义 Paint 并开启抗锯齿private val paint = Paint.apply {
style = Paint.Style.FILL
// 这里先用半透明白色Zuo基底
color = Color.argb
}
2️⃣ 用 BitmapShader Zuo模糊底纹
我们先把需要的背景图或者颜色画到一张 Bitmap 上,然后把它包装成 Shader,交给 Paint。
private fun createBlurShader: Shader {
// 简单高斯模糊实现
val bmp = Bitmap.createBitmap
val canvas = Canvas
canvas.drawColor // 清空
// 绘制原始内容,这里就用纯色示例
canvas.drawRect, height.toFloat,
Paint.apply { color = Color.WHITE })
// 用 BlurMaskFilter Zuo一次快速模糊
val blurPaint = Paint.apply {
isAntiAlias = true
maskFilter = BlurMaskFilter
}
val blurredBmp = Bitmap.createBitmap
val blurCanvas = Canvas
blurCanvas.drawBitmap
return BitmapShader(blurredBmp,
Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP)
}
3️⃣ 在 draw 中绘制圆角矩形 + 边框光晕
override fun draw {
// 绘制毛玻璃底层
paint.shader = blurShader
canvas.drawRoundRect
// 再绘制一层半透明白色叠加,让整体geng柔和
paint.shader = null
paint.color = Color.argb
canvas.drawRoundRect
// Zui后加个细细的光晕边框
if {
borderPaint.strokeWidth = strokeWidthPx
borderPaint.color = borderColor
canvas.drawRoundRect(rectFInset,
cornerRadiusPx - strokeWidthPx / 2,
cornerRadiusPx - strokeWidthPx / 2,
borderPaint)
}
}
4️⃣ 响应尺寸变化 & 圆角计算
override fun onBoundsChange {
super.onBoundsChange
rectF.set, bounds.top.toFloat,
bounds.right.toFloat, bounds.bottom.toFloat)
// 默认让圆角等于高度的一半,形成胶囊或圆形效果
if {
cornerRadiusPx = bounds.height / 2f
}
// 边框内缩半个宽度,防止被裁切掉
rectFInset.set(
bounds.left + strokeWidthPx / 2,
bounds.top + strokeWidthPx / 2,
bounds.right - strokeWidthPx / 2,
bounds.bottom - strokeWidthPx / 2)
// geng新模糊 Shader,尺寸变了就重新生成
blurShader = createBlurShader, bounds.height)
}
5️⃣ 暴露属性:圆角、边框宽度、是否亮色背景
var cornerRadius: Float
get = cornerRadiusPx
set {
cornerRadiusPx = value
customCorner = true
invalidateSelf
}
var borderWidth: Float = 0f
set {
field = value
strokeWidthPx = value * Resources.getSystem.displayMetrics.density
invalidateSelf
}
var lightBackground: Boolean = false
set {
field = value
// 根据亮暗切换不同的边框颜色和透明度梯度
borderColor = if Color.parseColor
else Color.parseColor
invalidateSelf
}
把自定义 Drawable 丢进 XML:简洁又优雅
写完 Kotlin/Java 类之后只要在 res/drawable 下新建一个 XML 声明文件,就Neng像普通资源一样使用啦。
然后在布局里直接套:
进阶玩法:RuntimeShader 打造geng真实的液态玻璃
Ru果你的 App Zui低支持 Android 12以上,那Ke以直接玩 RuntimeShader,省去手动模糊的繁琐步骤。
private val runtimeShader by lazy {
if {
RuntimeShader
} else null
}
override fun draw {
runtimeShader?.let { shader ->
shader.setFloatUniform("iResolution",
floatArrayOf.toFloat, bounds.height.toFloat))
shader.setFloatUniform
paint.shader = shader
canvas.drawRoundRect(rectF,
cornerRadiusPx,
cornerRadiusPx,
paint)
} ?: run {
// fallback to bitmap shader implementation...
}
}
S H A D E R_CODE 大概长这样:
uniform float2 iResolution;
uniform half4 colorStart;
uniform half4 colorEnd;
uniform float cornerRadius;
half4 main{
float2 uv = fragCoord / iResolution;
float t = * .5;
half4 col = mix;
// 简单圆角遮罩
float dist=length-cornerRadius,float2));
col.a *= smoothstep;
return col;
}
为什么 RuntimeShader geng好?
- 完全在 GPU 上跑,帧率稳如老狗。
- 支持实时动画,比如随手指滑动改变光照方向。
- 不用担心内存泄漏,因为不再生成临时 Bitmap。
实战案例:给卡片视图加上「玻璃」边框下面演示一下怎么把上面的 Drawable 用在 CardView 上,实现类似 iOS 卡片的磨砂外观:
然后在代码里给 ImageView 加上我们刚才写的「玻璃」背景:
val glassDrawable =
ContextCompat.getDrawable as MyGlassDrawable
// 根据卡片暗色还是亮色动态切换属性,下面随便写个示例:
glassDrawable.lightBackground =
resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_NO
ivBg.background = glassDrawable
Trouble Shooting 小贴士
- 别忘了在 onBoundsChange 把 rectF 和 rectFInset dougeng新,否则会出现绘制偏移。
- Ru果发现边框颜色kan不见,请检查 alpha 值是否太低。
- 在低版本设备上一定要走 bitmap‑shader 分支,否则 RuntimeShader 会直接报错。
- 想让圆角随父容器自动适配,只需要不手动设置 customCorner 为 true,让它默认取高度的一半。
- 对于 RecyclerView 中大量使用这种 Drawable 的场景,Zui好缓存一下创建好的实例,否则每次 bind dou会重新生成 bitmap,引起卡顿。
感想:自定义 Drawable 真香!说实话,我Zui开始也觉得自己写一个 drawable 太麻烦了直接去找第三方库吧。
结果自己撸出来以后才发现,这玩意儿真的是「一次写,多处用」的典范。
只要你掌握了上述几步,就Neng轻松搞定各种圆角、毛玻璃、渐变边框等炫酷需求——而且代码量根本不多,维护起来也hen舒服。
哈哈,Ru果你还有别的 UI 疑难杂症想聊聊,随时找我呀!咱就是说这篇文章Yi经帮你打开了一扇门,希望你们玩得开心~懂得的话点个赞呗~ 🤙🏻
.作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback