Я хочу иметь возможность поместить некоторый текст, например количество, которое может быть длиной до 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()
}
}
То, что я ищу, - это исправление, не позволяющее тексту идтинаружу диаметр круга.