优化人脸识别显示形状
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user