Как определить, касается ли canvas.drawText границы Rect? - PullRequest
0 голосов
/ 06 ноября 2019

Мне нужен собственный индикатор выполнения для проекта, и я смог нарисовать его, но я застрял с выравниванием текста внутри индикатора выполнения

class DashedCircularProgress : View {

private val START_ANGLE = -90
private lateinit var circleBounds: RectF
private var mLayoutHeight = 0
private var mLayoutWidth = 0
private var STROKE_WIDTH = 20.0f
var progressValue = 15f
val airPollution: String = "AIR POLLUTION"

private lateinit var paint: Paint
private lateinit var textPaint: Paint

constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
    init(attrs, 0)
}

constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(
    context,
    attrs,
    defStyleAttr
) {
    init(attrs, defStyleAttr)
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(
    context,
    attrs,
    defStyleAttr,
    defStyleRes
) {
    init(attrs, defStyleRes)
}

private fun init(attrs: AttributeSet, defStyleRes: Int) {
    val ta = context.obtainStyledAttributes(
        attrs,
        R.styleable.DashedCircularProgress, defStyleRes, 0
    )
    progressValue =
        ta.getFloat(
            R.styleable.DashedCircularProgress_dcp_progress,
            progressValue
        )
    paint = Paint(Paint.ANTI_ALIAS_FLAG)
    val dashPath = DashPathEffect(floatArrayOf(100f, 5f), 5.0.toFloat())
    paint.color = getRandomColor()
    //  paint.setPathEffect(dashPath)
    paint.style = Paint.Style.STROKE
    paint.strokeWidth = 35f

    ta.recycle()
}

private fun getRandomColor(): Int {
    val rnd = Random()
    val color = Color.argb(255, rnd.nextInt(256), rnd.nextInt(256), rnd.nextInt(256))
    return color
}

override fun onSizeChanged(newWidth: Int, newHeight: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(newWidth, newHeight, oldw, oldh)
    mLayoutWidth = newWidth
    mLayoutHeight = newHeight
    setupBounds()
}

private fun setupBounds() {

    val minValue = Math.min(mLayoutWidth, mLayoutHeight)

    val xOffset = mLayoutWidth - minValue
    val yOffset = mLayoutHeight - minValue

    val paddingTop = this.paddingTop + yOffset / 2
    val paddingBottom = this.paddingBottom + yOffset / 2
    val paddingLeft = this.paddingLeft + xOffset / 2
    val paddingRight = this.paddingRight + xOffset / 2

    val width = width
    val height = height

    circleBounds = RectF(
        paddingLeft.toFloat() + STROKE_WIDTH * 2,
        paddingTop.toFloat() + STROKE_WIDTH * 2,
        mLayoutWidth.toFloat() - STROKE_WIDTH * 2 - paddingRight,
        mLayoutHeight.toFloat() - STROKE_WIDTH * 2 - paddingBottom
    )
    textPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    textPaint.textSize = 42f
    textPaint.color = Color.BLUE
   /* val textWidth = textPaint.measureText(airPollution)
    if (circleBounds.width() /2< textWidth) {
        Handler().postDelayed({
            textPaint.textSize = 18f
            invalidate()
        }, 5000)
    }*/
    //  textPaint.getTextBounds(airPollution,0,airPollution.length,circleBounds.toRect())
    Log.d("Values", "circleBounds")
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    val degree = 90
    val progressAngle = getProgressAngle(progressValue)
    for (i in 0 until (progressAngle / 90f).toInt() + 1) {
        paint.color = getColorForIndex(i)
        var progressToLoad = 90f
        val degreeValue = (degree * i)

        if (i == (progressAngle / 90).toInt()) {
            progressToLoad = (progressAngle - degreeValue)
            for (j in 0 until (progressToLoad / 22.5).toInt()) {
                canvas.drawArc(
                    circleBounds,
                    (START_ANGLE + degreeValue).toFloat() + (22 * j),
                    if (j == 3) 22f else 20f,
                    false,
                    paint
                )
            }
        } else {
            for (k in 0 until 4 step 1) {
                canvas.drawArc(
                    circleBounds,
                    (START_ANGLE + degreeValue).toFloat() + (22 * k),
                    if (k == 3) 22f else 20f,
                    false,
                    paint
                )
            }

        }
        //    canvas.drawText(progressValue.toString(),(circleBounds.width()/2),(circleBounds.height()/2),paint)
        //canvas.drawText("AIR POLLUTION",0f,0f ,textPaint)
        canvas.drawText(
            "AIR POLLUTION",
            circleBounds.width() / 2,
            circleBounds.height() / 2,
            textPaint
        )
    }
}


private fun getProgressAngle(percent: Float): Float {
    return percent / 100.toFloat() * 360
}

fun setProgress(progressValue: Float) {
    this.progressValue = progressValue
    invalidate()
}

private fun getColorForIndex(index: Int): Int {
    when (index) {
        0 -> {
            return Color.RED
        }
        1 -> {
            return Color.YELLOW
        }
        2 -> {
            return Color.GREEN
        }
        3 -> {
            return Color.BLUE
        }
        else -> return Color.MAGENTA
    }
   }
}

enter image description here

Здесь текст касается индикатора выполнения, в этом случае мне нужно изменить размер текста до меньшего значения. Это то, что я пытался решить, и я не уверен, что это хороший подход к этому

val textWidth = textPaint.measureText(airPollution)
    if (circleBounds.width() /2< textWidth) {
            textPaint.textSize = 18f
            invalidate()
    }
...