Created
July 13, 2019 13:56
-
-
Save m4xp1/02bd4a0993664d271d4ee06dcc70538c to your computer and use it in GitHub Desktop.
Resized text view
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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