优化人脸识别显示形状

This commit is contained in:
2026-02-11 17:00:08 +08:00
parent 462755824d
commit 59b3ad72fe
5 changed files with 144 additions and 174 deletions
@@ -0,0 +1,122 @@
package com.sw.dualscreen.view
import androidx.core.graphics.toColorInt
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
/**
* 带镂空椭圆的矩形自定义View
* 矩形尺寸:400dp × 510dp,背景色 #FFF4FAFF
* 镂空椭圆尺寸:400dp × 436dp,居中显示
*/
class HollowOvalInRectView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
// 基础尺寸配置(dp
private val rectWidthDp = 400f // 矩形宽度
private val rectHeightDp = 510f // 矩形高度
private val ovalWidthDp = 400f // 椭圆宽度
private val ovalHeightDp = 436f // 椭圆高度
// 转换后的像素尺寸
private val rectWidth: Float
private val rectHeight: Float
private var ovalWidth: Float
private var ovalHeight: Float
// 矩形背景画笔(颜色 #FFF4FAFF)
private val rectPaint = Paint().apply {
isAntiAlias = true
color = "#FFF4FAFF".toColorInt() // 矩形背景色
// color = "#FFFFFF".toColorInt() // 矩形背景色
style = Paint.Style.FILL
}
// 镂空椭圆画笔(核心:DST_OUT模式实现镂空)
private val hollowOvalPaint = Paint().apply {
isAntiAlias = true
color = Color.BLACK // 颜色不影响镂空效果,仅需非透明即可
style = Paint.Style.FILL
xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
}
// 椭圆路径(复用避免重复创建)
private val ovalPath = Path()
init {
// dp转px,保证多设备尺寸一致
val density = resources.displayMetrics.density
rectWidth = rectWidthDp * density
rectHeight = rectHeightDp * density
ovalWidth = ovalWidthDp * density
ovalHeight = ovalHeightDp * density
// 关键配置:关闭硬件加速保证Xfermode生效
setLayerType(LAYER_TYPE_HARDWARE, null)
// 视图背景透明,避免干扰
setBackgroundColor(Color.TRANSPARENT)
}
/**
* 强制设置View尺寸为指定的矩形尺寸
*/
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val targetWidth = MeasureSpec.makeMeasureSpec(rectWidth.toInt(), MeasureSpec.EXACTLY)
val targetHeight = MeasureSpec.makeMeasureSpec(rectHeight.toInt(), MeasureSpec.EXACTLY)
super.onMeasure(targetWidth, targetHeight)
}
/**
* 核心绘制逻辑:先画矩形,再画镂空椭圆
*/
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 保存画布图层,确保Xfermode生效
val layerId = canvas.saveLayer(0f, 0f, width.toFloat(), height.toFloat(), null)
// 1. 绘制底层矩形(背景色 #FFF4FAFF)
canvas.drawRect(0f, 0f, width.toFloat(), height.toFloat(), rectPaint)
// 2. 计算椭圆居中坐标(椭圆宽度和矩形宽度一致,仅垂直居中)
val ovalTop = (rectHeight - ovalHeight) / 2 // 椭圆顶部偏移
val ovalBottom = ovalTop + ovalHeight // 椭圆底部坐标
// 3. 绘制镂空椭圆(居中)
ovalPath.reset()
ovalPath.addOval(
0f, // 左:和矩形左对齐(宽度一致)
ovalTop, // 上:垂直居中
rectWidth, // 右:和矩形右对齐
ovalBottom, // 下
Path.Direction.CW
)
canvas.drawPath(ovalPath, hollowOvalPaint)
// 恢复画布状态
canvas.restoreToCount(layerId)
}
// 扩展方法:支持动态修改矩形背景色
fun updateRectBackgroundColor(colorHex: String) {
try {
rectPaint.color = Color.parseColor(colorHex)
invalidate() // 重绘视图
} catch (e: IllegalArgumentException) {
e.printStackTrace()
}
}
// 扩展方法:支持动态修改椭圆尺寸(可选)
fun updateOvalSize(widthDp: Float, heightDp: Float) {
val density = resources.displayMetrics.density
ovalWidth = widthDp * density
ovalHeight = heightDp * density
invalidate()
}
}