Merge "Cache Typeface for later animation" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-13 06:14:36 +00:00
committed by Android (Google) Code Review
2 changed files with 58 additions and 1 deletions

View File

@@ -21,7 +21,9 @@ import android.animation.AnimatorListenerAdapter
import android.animation.TimeInterpolator import android.animation.TimeInterpolator
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Typeface
import android.text.Layout import android.text.Layout
import android.util.SparseArray
private const val TAG_WGHT = "wght" private const val TAG_WGHT = "wght"
private const val DEFAULT_ANIMATION_DURATION: Long = 300 private const val DEFAULT_ANIMATION_DURATION: Long = 300
@@ -72,6 +74,8 @@ class TextAnimator(
}) })
} }
private val typefaceCache = SparseArray<Typeface?>()
fun updateLayout(layout: Layout) { fun updateLayout(layout: Layout) {
textInterpolator.layout = layout textInterpolator.layout = layout
} }
@@ -120,7 +124,12 @@ class TextAnimator(
textInterpolator.targetPaint.textSize = textSize textInterpolator.targetPaint.textSize = textSize
} }
if (weight >= 0) { if (weight >= 0) {
textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight" // Paint#setFontVariationSettings creates Typeface instance from scratch. To reduce the
// memory impact, cache the typeface result.
textInterpolator.targetPaint.typeface = typefaceCache.getOrElse(weight) {
textInterpolator.targetPaint.fontVariationSettings = "'$TAG_WGHT' $weight"
textInterpolator.targetPaint.typeface
}
} }
if (color != null) { if (color != null) {
textInterpolator.targetPaint.color = color textInterpolator.targetPaint.color = color
@@ -155,3 +164,12 @@ class TextAnimator(
} }
} }
} }
private fun <V> SparseArray<V>.getOrElse(key: Int, defaultValue: () -> V): V {
var v = get(key)
if (v == null) {
v = defaultValue()
put(key, v)
}
return v
}

View File

@@ -18,12 +18,14 @@ package com.android.keyguard
import android.animation.AnimatorListenerAdapter import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.graphics.Typeface
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.text.Layout import android.text.Layout
import android.text.StaticLayout import android.text.StaticLayout
import android.text.TextPaint import android.text.TextPaint
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
@@ -140,4 +142,41 @@ class TextAnimatorTest : SysuiTestCase() {
verify(animationEndCallback).run() verify(animationEndCallback).run()
verify(valueAnimator).removeListener(eq(captor.value)) verify(valueAnimator).removeListener(eq(captor.value))
} }
@Test
fun testCacheTypeface() {
val layout = makeLayout("Hello, World", PAINT)
val valueAnimator = mock(ValueAnimator::class.java)
val textInterpolator = mock(TextInterpolator::class.java)
val paint = TextPaint().apply {
typeface = Typeface.createFromFile("/system/fonts/Roboto-Regular.ttf")
}
`when`(textInterpolator.targetPaint).thenReturn(paint)
val textAnimator = TextAnimator(layout, {}).apply {
this.textInterpolator = textInterpolator
this.animator = valueAnimator
}
textAnimator.setTextStyle(
weight = 400,
animate = true
)
val prevTypeface = paint.typeface
textAnimator.setTextStyle(
weight = 700,
animate = true
)
assertThat(paint.typeface).isNotSameInstanceAs(prevTypeface)
textAnimator.setTextStyle(
weight = 400,
animate = true
)
assertThat(paint.typeface).isSameInstanceAs(prevTypeface)
}
} }