You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 14:39:02