72 lines
2.8 KiB
Kotlin
72 lines
2.8 KiB
Kotlin
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
|
|
}
|
|
} |