Android 实现徽章(badge)外围透明遮罩的最优方法是什么
实现徽章外围透明遮罩的最优方案
核心思路是通过离屏绘制结合图形混合模式,挖去徽章所在位置的遮罩层区域,实现外围半透明、徽章区域完全通透的效果,该方案性能开销低、适配所有徽章形状,是当前Android开发中的最优实现。
传统View体系实现
核心依赖PorterDuffXfermode的清除模式实现遮罩挖空,步骤如下:
- 提前开启自定义View的离屏缓冲:
setLayerType(LAYER_TYPE_HARDWARE, null),避免混合绘制时出现黑色底噪 - 绘制全容器的半透明遮罩层
- 初始化画笔并设置Xfermode为
PorterDuffXfermode(PorterDuff.Mode.CLEAR) - 在徽章对应位置绘制和徽章形状一致的图形,圆形徽章直接画圆、异形徽章直接传入徽章Bitmap绘制即可自动匹配形状挖空
- 绘制完成后清除画笔的Xfermode避免影响后续绘制逻辑
代码示例:
override fun onDraw(canvas: Canvas) { super.onDraw(canvas) // 绘制半透明遮罩,透明度、颜色可自定义 canvas.drawColor(0x99000000) // 配置清除模式画笔 val clearPaint = Paint().apply { isAntiAlias = true xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) } // 按徽章位置、形状挖空遮罩,此处以圆形徽章为例 canvas.drawCircle(badgeCenterX, badgeCenterY, badgeRadius, clearPaint) // 最后绘制上层徽章内容 canvas.drawBitmap(badgeBitmap, badgeLeft, badgeTop, null) }
Jetpack Compose实现
Compose原生支持混合模式属性,代码更简洁,无需自定义View:
Box(modifier = Modifier.fillMaxSize()) { // 底层原始页面内容 OriginalPageContent() // 半透明遮罩层 Box( modifier = Modifier .fillMaxSize() .graphicsLayer { compositingStrategy = CompositingStrategy.Offscreen } .background(Color.Black.copy(alpha = 0.6f)) ) { // 挖空徽章对应位置,异形徽章替换为自定义Shape即可 Box( modifier = Modifier .size(badgeSize) .align(Alignment.TopEnd) // 和徽章位置完全对齐 .blendMode(BlendMode.Clear) .clip(CircleShape) ) } // 上层绘制徽章组件 BadgeComposable(modifier = Modifier.align(Alignment.TopEnd).size(badgeSize)) }
内容的提问来源于stack exchange,提问作者Ilya Mashin
相关产品推荐
相关产品推荐

