Skip to content

Instantly share code, notes, and snippets.

@m4xp1
Created July 13, 2019 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save m4xp1/02bd4a0993664d271d4ee06dcc70538c to your computer and use it in GitHub Desktop.
Save m4xp1/02bd4a0993664d271d4ee06dcc70538c to your computer and use it in GitHub Desktop.
Resized text view
package com.example.android.basictransition
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.support.annotation.ColorInt
import android.util.AttributeSet
import android.util.TypedValue
import android.view.View
class NumberView : View {
// <editor-fold desc="Properties">
var letterSpacing
get() = paint.letterSpacing
set(value) {
paint.letterSpacing = value
requestLayout()
invalidate()
}
var textColor = Color.BLACK
@ColorInt get
set(@ColorInt value) {
field = value
invalidate()
}
var text: String = ""
set(value) {
field = value
requestLayout()
invalidate()
}
// </editor-fold>
private val paint = Paint()
private val textRect = Rect()
private val defaultTextSize = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_SP, 12f, resources.displayMetrics)
private var measuredTextSize = 0f
constructor(context: Context) : super(context) {
init(context)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init(context, attrs)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) :
super(context, attrs, defStyleAttr) {
init(context, attrs, defStyleAttr)
}
@Suppress("UNUSED_PARAMETER")
private fun init(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) {
context.theme.obtainStyledAttributes(
attrs,
R.styleable.NumberView,
0,
0
).apply {
try {
letterSpacing = getFloat(R.styleable.NumberView_android_letterSpacing, 0.1f)
textColor = getColor(R.styleable.NumberView_android_textColor, textColor)
text = getString(R.styleable.NumberView_android_text) ?: text
} finally {
recycle()
}
}
paint.isAntiAlias = true
paint.color = textColor
paint.textSize = defaultTextSize
paint.textAlign = Paint.Align.CENTER
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
paint.textSize = defaultTextSize
paint.getTextBounds(text, 0, text.length, textRect)
measuredTextSize = calculateTextSize(measuredWidth, measuredHeight)
paint.textSize = 0f
}
private fun calculateTextSize(width: Int, height: Int): Float {
if (textRect.width() == 0 || textRect.height() == 0) {
return 0f
}
val ratio = Math.min(
(width - height / 3f) / textRect.width(),
(height - height / 3f) / textRect.height())
return defaultTextSize * ratio
}
// Fix text shake during animation
private fun filteredValue(requested: Float, current: Float, measured: Float): Float {
return when {
current == 0f || requested == measured -> requested
requested < measured -> Math.max(requested, current)
else -> Math.min(requested, current)
}
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (!text.isEmpty()) {
val textSize = calculateTextSize(width, height)
paint.color = textColor
paint.textSize = filteredValue(textSize, paint.textSize, measuredTextSize)
val descent = paint.fontMetrics.descent
val ascent = paint.fontMetrics.ascent
val baseline = height / 2f + (descent - ascent) / 2f - descent
canvas.drawText(text, 0, text.length, width / 2f, baseline, paint)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment