package com.sw.dualscreen.view import android.content.Context import android.graphics.* import android.util.AttributeSet import android.util.Log import android.view.View import androidx.core.content.ContextCompat import androidx.core.graphics.toColorInt import kotlin.math.roundToInt class HollowCircleRectView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : View(context, attrs, defStyleAttr) { // 1. 先定义dp值,再统一转px(避免多次转换误差) private val rectWidthDp = 400f private val rectHeightDp = 510f private val circleRadiusDp = 200f // 直径400dp → 半径200dp(固定正圆关键) // 2. 转px后的值(只计算一次,避免onDraw重复计算) private val rectWidthPx: Float = dp2px(rectWidthDp) private val rectHeightPx: Float = dp2px(rectHeightDp) private val circleRadiusPx: Float = dp2px(circleRadiusDp) // 画笔和路径(复用避免重复创建) private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private val path = Path() init { // paint.color = "#FFE7EFF8".toColorInt() paint.color = "#FFF4FAFF".toColorInt() paint.style = Paint.Style.FILL // 强制关闭硬件加速可能的渲染偏差(关键) setLayerType(LAYER_TYPE_SOFTWARE, null) } override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { // 强制View尺寸为精准px值,避免父布局干扰 val rectWidthPxInt = rectWidthPx.toInt() val rectHeightPxInt = rectHeightPx.toInt() Log.d("HollowCircleRectView", "onMeasure: $rectWidthPxInt,$rectHeightPxInt") setMeasuredDimension(rectWidthPxInt, rectHeightPxInt) } override fun onDraw(canvas: Canvas) { super.onDraw(canvas) path.reset() // 1. 添加矩形路径(精准px值,无偏差) path.addRect(0f, 0f, rectWidthPx, rectHeightPx, Path.Direction.CW) // 2. 添加圆形路径(固定半径,绝对正圆) val circleX = rectWidthPx / 2 // 水平居中:200dp转px val circleY = rectHeightPx / 2 // 垂直居中:340dp转px // 核心修复:用固定半径circleRadiusPx,而非直径/2(避免浮点运算偏差) Log.d("HollowCircleRectView", "onDraw: $circleX,$circleY,$circleRadiusPx") path.addCircle(circleX, circleY, circleRadiusPx, Path.Direction.CW) // 3. 填充规则+绘制 path.fillType = Path.FillType.EVEN_ODD canvas.drawPath(path, paint) } // 精准dp转px(四舍五入避免小数偏差) private fun dp2px(dp: Float): Float { val density = context.resources.displayMetrics.density return (dp * density).roundToInt().toFloat() // 四舍五入到整数px } }