1. 概述
1.1 背景
蒙层是提升用户界面视觉效果和交互体验的关键元素。蒙层主要用于:
- 提升内容可读性:在图片上叠加文字时,通过渐变蒙层增强文字对比度
- 视觉层次感:区分前景内容和背景图片
- 品牌视觉统一:通过主题色蒙层实现品牌色调统一
- 交互反馈:模糊蒙层用于弹窗背景,增强焦点感
1.2 技术架构
蒙层体系
├── 渐变蒙层(GradientMask)
│ ├── 底部渐变蒙层
│ ├── 顶部渐变蒙层
│ └── 多段渐变蒙层
├── 高斯模糊蒙层(BlurMask)
│ ├── 实时模糊
│ └── 区域模糊
└── 纯色遮罩
├── 半透明遮罩
└── 交互遮罩
2. 蒙层类型与实现
2.1 渐变蒙层(GradientMask)
2.1.1 底部渐变蒙层
使用场景:底部功能区,提升文字和图标可读性
实现原理:
/**
* 底部蒙层生成流程
* 1. 提取图片主色调(Palette API)
* 2. HSV颜色空间转换
* 3. 生成多段渐变 Drawable
* 4. 动态设置蒙层高度
*/
// 2. 转换HSB参数到HSV色彩空间(Android中HSV的V对应亮度)
val hsv = FloatArray(3).apply {
// 从主色中获取原始HSV,再替换为目标H/S/V
Color.colorToHSV(dominantColor, this)
this[0] = hue.coerceIn(0f, 360f) // 色相限制在0-360
this[1] = (saturation / 100f).coerceIn(0f, 1f) // 饱和度转换为0-1范围
this[2] = (brightness / 100f).coerceIn(0f, 1f) // 亮度转换为0-1范围
}
// 3. 计算渐变的起始和结束颜色(处理Alpha值)
val startColor = Color.HSVToColor(
(startAlpha * 255).roundToInt().coerceIn(0, 255),
hsv
)
val endColor = Color.HSVToColor(
(endAlpha * 255).roundToInt().coerceIn(0, 255),
hsv
)
// 4. 创建并配置渐变Drawable
return GradientDrawable(orientation, intArrayOf(startColor, endColor)).apply {
// 可根据需求添加其他配置,如圆角
if (radiusPx != -1) {
cornerRadius = radiusPx.toFloat() // 示例:添加圆角(需实现dp转px)
}
}
| 位置 | 透明度(Alpha) | 说明 |
|---|---|---|
| 顶部(0%) | 0 (0x00) | 完全透明 |
| 中间(50%) | 128 (0x80) | 半透明 |
| 底部(100%) | 192 (0xC0) | 较强遮盖 |
2.1.2 顶部渐变蒙层
使用场景:顶部导航栏区域,避免图片内容干扰状态栏图标
实现特点:
- 高度:120dp(固定)
- 方向:从上到下渐变(TOP_BOTTOM)
- 颜色:通常为黑色到透明
2.1.3 多段渐变蒙层
使用场景:需要更平滑的渐变过渡
设计规范:
梯度位置 不透明度
0% 0% (完全透明)
21% 10% (微弱遮盖)
57% 35% (中等遮盖)
78% 55% (较强遮盖)
100% 70% (强遮盖)
override fun onBoundsChange(bounds: android.graphics.Rect) {
super.onBoundsChange(bounds)
// 从上到下的渐变
gradient = LinearGradient(
0f,
bounds.top.toFloat(),
0f,
bounds.bottom.toFloat(),
colors,
positions,
Shader.TileMode.CLAMP
)
paint.shader = gradient
// 创建只在下半部分有圆角的路径,使用 addRoundRect 与图片圆角实现保持一致
val left = bounds.left.toFloat()
val top = bounds.top.toFloat()
val right = bounds.right.toFloat()
val bottom = bounds.bottom.toFloat()
path.reset()
rectF.set(left, top, right, bottom)
// 使用 addRoundRect 创建圆角路径,与 RoundImageView 的实现方式保持一致
// rids 格式:左上x, 左上y, 右上x, 右上y, 右下x, 右下y, 左下x, 左下y
val rids = floatArrayOf(
0f, 0f, // 左上角(直角)
0f, 0f, // 右上角(直角)
cornerRadius, cornerRadius, // 右下角(圆角)
cornerRadius, cornerRadius // 左下角(圆角)
)
path.addRoundRect(rectF, rids, Path.Direction.CW)
invalidateSelf()
}
2.2 高斯模糊蒙层(BlurMask)
2.2.1 实时高斯模糊
使用场景:弹窗背景
// 适配 Android 12+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// 1. 创建高斯模糊效果:radius(模糊半径),越大约模糊但性能越低(建议≤25)
val blurEffect = RenderEffect.createBlurEffect(
15f, // 水平模糊半径
15f, // 垂直模糊半径
Shader.TileMode.CLAMP // 边界模式(CLAMP=重复边缘像素,避免黑边)
)
// 2. 给目标 View 设置模糊(如布局、ImageView、TextView)
targetView.setRenderEffect(blurEffect)
// 可选:模糊 + 颜色叠加(避免模糊后过亮/过暗)
val colorFilter = ColorFilter.createBlendModeFilter(
Color.argb(128, 0, 0, 0), // 半透明黑色叠加
BlendMode.SRC_ATOP
)
targetView.setColorFilter(colorFilter)
}
2.2.2 区域高斯模糊
使用场景:特定区域模糊
2.3 纯色遮罩(SolidMask)
2.3.1 半透明遮罩
使用场景:弹窗背景、引导蒙层
实现方式:
// 方式1:View 背景
val maskView = View(context)
maskView.setBackgroundColor(0x80000000) // 50% 透明黑色
// 方式2:Drawable
val colorDrawable = ColorDrawable(0x80000000)
imageView.foreground = colorDrawable