如何在Android中实现带卡片镂空效果的证件拍照界面
解决方案
你现在的实现里直接叠加了一层全局半透明黑色RelativeLayout,这种方式没法直接做出区域镂空效果,推荐以下两种可行方案:
方案1:自定义镂空遮罩View(推荐,适配性最高)
你可以自定义一个View作为半透明遮罩层,替换现有单独的半透明黑色RelativeLayout,步骤如下:
- 新建自定义View类
CameraMaskView,重写绘制逻辑:
class CameraMaskView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { // 半透明遮罩颜色,对应你原来的50%透明度黑色 private val maskColor = Color.parseColor("#80000000") // 镂空卡片的圆角,可根据实际需求调整数值 private val cornerRadius = resources.getDimension(R.dimen._8sdp) private val hollowRect = RectF() private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private val clearXfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { super.onSizeChanged(w, h, oldw, oldh) // 计算镂空区域位置,和你原有布局里卡片区域位置对齐 val horizontalMargin = resources.getDimension(R.dimen._40sdp) val topMargin = resources.getDimension(R.dimen._120sdp) val cardHeight = resources.getDimension(R.dimen._150sdp) hollowRect.apply { left = horizontalMargin top = topMargin right = w - horizontalMargin bottom = topMargin + cardHeight } } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) // 开启离屏缓冲,避免CLEAR模式清空底层预览内容 setLayerType(LAYER_TYPE_HARDWARE, paint) // 绘制全页面半透明遮罩 canvas.drawColor(maskColor) // 设置混合模式为清除,画出镂空区域 paint.xfermode = clearXfermode canvas.drawRoundRect(hollowRect, cornerRadius, cornerRadius, paint) // 重置混合模式 paint.xfermode = null } }
- 替换布局中的半透明层
把原有布局里的这段代码:
<RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:alpha="0.5" android:background="@color/black" />
替换为自定义的遮罩View:
<com.你的包名路径.CameraMaskView android:layout_width="match_parent" android:layout_height="match_parent" />
- 删除冗余代码
你原有布局里的viewFinderCard这个PreviewView是冗余的,直接删掉即可,镂空区域会直接显示底层viewFinder的摄像头预览内容。
方案2:图层拼接实现(无需自定义View,适合快速开发)
你可以用9块纯色View拼接出遮罩:上下左右四个半透明黑边,加上四个边角的半透明黑块,中间留空即为镂空区域。这种方式不需要写自定义View代码,但是适配不同屏幕尺寸时灵活性较差,调整参数的成本更高。
内容的提问来源于stack exchange,提问作者Karan Mehta
相关产品推荐
相关产品推荐

