Нарисуйте круг с текстом, не превышающим диаметр - PullRequest
0 голосов
/ 11 ноября 2019

Я хочу иметь возможность поместить некоторый текст, например количество, которое может быть длиной до 7 цифр (1000000) внутри круга, используя холст при рисовании. Проблема в том, что на экране некоторых устройств текст выходит за пределы диаметра окружности, указанной ниже. Я вставляю код для рисования пользовательского круга с текстом.

Код, который у меня есть для рисования круга и текста внутри него. Код работает с небольшим числом, таким как 938, но если число превышает 5 или более чисел на некоторых устройствах, оно выходит за пределы диаметра.

class CircularProgressBar @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs,   defStyleAttr) {

private var mViewWidth: Int = 0
private var mViewHeight: Int = 0
private val mStartAngle = -90f
private var mSweepAngle = 0f
private val mMaxSweepAngle = 360f
private var mStrokeWidth = 20
private val mAnimationDuration = 400
private val mMaxProgress = 100
private var mDrawText = true
private var amount:String? = null
private var currency:String? = null
private var mProgressColor = Color.BLACK
private var mTextColor = Color.BLACK

private val mPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG)


override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    initMeasurements()
    drawBackGroundArch(canvas)
    drawOutlineArc(canvas)
    if (mDrawText) {
        drawPercentageText(canvas)
        drawAmountText(canvas)
    }
}

private fun initMeasurements() {
    mViewWidth = width
    mViewHeight = height
}

private fun drawOutlineArc(canvas: Canvas) {

    val diameter = min(mViewWidth, mViewHeight) - (mStrokeWidth -25)* 2

    val outerOval = RectF(
        mStrokeWidth.toFloat(),
        mStrokeWidth.toFloat(),
        diameter.toFloat(),
        diameter.toFloat()
    )

    mPaint.color = mProgressColor
    mPaint.strokeWidth = mStrokeWidth.toFloat()
    mPaint.isAntiAlias = true
    mPaint.strokeCap =  Paint.Cap.ROUND
    mPaint.style = Paint.Style.STROKE
    canvas.drawArc(outerOval, mStartAngle, mSweepAngle, false, mPaint)
}

private fun drawBackGroundArch(canvas: Canvas) {

    val diameter = min(mViewWidth, mViewHeight) - (mStrokeWidth -25) * 2

    val outerOval = RectF(
        mStrokeWidth.toFloat(),
        mStrokeWidth.toFloat(),
        diameter.toFloat(),
        diameter.toFloat()
    )

    mPaint.color = Color.LTGRAY
    mPaint.strokeWidth = mStrokeWidth.toFloat()
    mPaint.isAntiAlias = true
    mPaint.strokeCap =  Paint.Cap.ROUND
    mPaint.style = Paint.Style.STROKE

    canvas.drawArc(outerOval, mStartAngle, mMaxSweepAngle, false, mPaint)
}


private fun drawPercentageText(canvas: Canvas) {
    mPaint.textSize = mViewWidth.coerceAtMost(mViewHeight) / 7f
    mPaint.textAlign = Paint.Align.CENTER
    mPaint.strokeWidth = 0f
    mPaint.color = mTextColor

    // Center text
    val xPos = canvas.width / 2
    val yPos = (canvas.height / 2 - (mPaint.descent() + mPaint.ascent()) / 2).toInt() - 60

    canvas.drawText(
        calcProgressFromSweepAngle(mSweepAngle).toString() + "%",
        xPos.toFloat(),
        yPos.toFloat(),
        mPaint
    )
}

private fun drawAmountText(canvas: Canvas) {
    mPaint.textSize = mViewWidth.coerceAtMost(mViewHeight) / 11f
    mPaint.textAlign = Paint.Align.CENTER
    mPaint.strokeWidth = 0f
    mPaint.color = mTextColor

    // Center text
    val xPos = canvas.width / 2
    val yPos = (canvas.height / 2 - (mPaint.descent() + mPaint.ascent()) / 2).toInt() + 40

    canvas.drawText(amount +  " " + currency,
        xPos.toFloat(),
        yPos.toFloat(),
        mPaint
    )
}

private fun calcSweepAngleFromProgress(progress: Int): Float {
    return mMaxSweepAngle / mMaxProgress * progress
}

private fun calcProgressFromSweepAngle(sweepAngle: Float): Int {
    return (sweepAngle * mMaxProgress / mMaxSweepAngle).toInt()
}

fun setProgress(progress: Int) {
    val animator = ValueAnimator.ofFloat(mSweepAngle, calcSweepAngleFromProgress(progress))
    animator.interpolator = DecelerateInterpolator()
    animator.duration = mAnimationDuration.toLong()
    animator.addUpdateListener { valueAnimator ->
        mSweepAngle = valueAnimator.animatedValue as Float
        invalidate()
    }
    animator.start()
}

fun setProgressColor(color: Int) {
    mProgressColor = color
    invalidate()
}

fun setProgressWidth(width: Int) {
    mStrokeWidth = width
    invalidate()
}

  fun setAmountText(amount:String){
      this.amount = amount
      invalidate()
  }

  fun setCurrencyType(currency:String){
    this.currency = currency
  }

  fun setTextColor(color: Int) {
    mTextColor = color
    invalidate()
   }
}

То, что я ищу, - это исправление, не позволяющее тексту идтинаружу диаметр круга.

...