Merge "Fix flicker when starting folding" into tm-qpr-dev

This commit is contained in:
Nicolò Mazzucato
2022-12-21 13:06:12 +00:00
committed by Android (Google) Code Review
3 changed files with 77 additions and 21 deletions

View File

@@ -90,8 +90,13 @@ object LiftReveal : LightRevealEffect {
class LinearLightRevealEffect(private val isVertical: Boolean) : LightRevealEffect {
// Interpolator that reveals >80% of the content at 0.5 progress, makes revealing faster
private val interpolator = PathInterpolator(/* controlX1= */ 0.4f, /* controlY1= */ 0f,
/* controlX2= */ 0.2f, /* controlY2= */ 1f)
private val interpolator =
PathInterpolator(
/* controlX1= */ 0.4f,
/* controlY1= */ 0f,
/* controlX2= */ 0.2f,
/* controlY2= */ 1f
)
override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {
val interpolatedAmount = interpolator.getInterpolation(amount)
@@ -116,17 +121,17 @@ class LinearLightRevealEffect(private val isVertical: Boolean) : LightRevealEffe
if (isVertical) {
scrim.setRevealGradientBounds(
left = scrim.width / 2 - (scrim.width / 2) * gradientBoundsAmount,
left = scrim.viewWidth / 2 - (scrim.viewWidth / 2) * gradientBoundsAmount,
top = 0f,
right = scrim.width / 2 + (scrim.width / 2) * gradientBoundsAmount,
bottom = scrim.height.toFloat()
right = scrim.viewWidth / 2 + (scrim.viewWidth / 2) * gradientBoundsAmount,
bottom = scrim.viewHeight.toFloat()
)
} else {
scrim.setRevealGradientBounds(
left = 0f,
top = scrim.height / 2 - (scrim.height / 2) * gradientBoundsAmount,
right = scrim.width.toFloat(),
bottom = scrim.height / 2 + (scrim.height / 2) * gradientBoundsAmount
top = scrim.viewHeight / 2 - (scrim.viewHeight / 2) * gradientBoundsAmount,
right = scrim.viewWidth.toFloat(),
bottom = scrim.viewHeight / 2 + (scrim.viewHeight / 2) * gradientBoundsAmount
)
}
}
@@ -234,7 +239,14 @@ class PowerButtonReveal(
* transparent center. The center position, size, and stops of the gradient can be manipulated to
* reveal views below the scrim as if they are being 'lit up'.
*/
class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
class LightRevealScrim
@JvmOverloads
constructor(
context: Context?,
attrs: AttributeSet?,
initialWidth: Int? = null,
initialHeight: Int? = null
) : View(context, attrs) {
/** Listener that is called if the scrim's opaqueness changes */
lateinit var isScrimOpaqueChangedListener: Consumer<Boolean>
@@ -277,6 +289,17 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
var revealGradientWidth: Float = 0f
var revealGradientHeight: Float = 0f
/**
* Keeps the initial value until the view is measured. See [LightRevealScrim.onMeasure].
*
* Needed as the view dimensions are used before the onMeasure pass happens, and without preset
* width and height some flicker during fold/unfold happens.
*/
internal var viewWidth: Int = initialWidth ?: 0
private set
internal var viewHeight: Int = initialHeight ?: 0
private set
/**
* Alpha of the fill that can be used in the beginning of the animation to hide the content.
* Normally the gradient bounds are animated from small size so the content is not visible, but
@@ -375,6 +398,11 @@ class LightRevealScrim(context: Context?, attrs: AttributeSet?) : View(context,
invalidate()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
viewWidth = measuredWidth
viewHeight = measuredHeight
}
/**
* Sets bounds for the transparent oval gradient that reveals the views below the scrim. This is
* simply a helper method that sets [revealGradientCenter], [revealGradientWidth], and

View File

@@ -159,18 +159,24 @@ constructor(
ensureOverlayRemoved()
val newRoot = SurfaceControlViewHost(context, context.display!!, wwm)
val newView =
LightRevealScrim(context, null).apply {
revealEffect = createLightRevealEffect()
isScrimOpaqueChangedListener = Consumer {}
revealAmount =
when (reason) {
FOLD -> TRANSPARENT
UNFOLD -> BLACK
}
}
val params = getLayoutParams()
val newView =
LightRevealScrim(
context,
attrs = null,
initialWidth = params.width,
initialHeight = params.height
)
.apply {
revealEffect = createLightRevealEffect()
isScrimOpaqueChangedListener = Consumer {}
revealAmount =
when (reason) {
FOLD -> TRANSPARENT
UNFOLD -> BLACK
}
}
newRoot.setView(newView, params)
if (onOverlayReady != null) {

View File

@@ -20,6 +20,7 @@ import android.testing.AndroidTestingRunner
import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Before
@@ -36,7 +37,7 @@ class LightRevealScrimTest : SysuiTestCase() {
@Before
fun setUp() {
scrim = LightRevealScrim(context, null)
scrim = LightRevealScrim(context, null, DEFAULT_WIDTH, DEFAULT_HEIGHT)
scrim.isScrimOpaqueChangedListener = Consumer { opaque ->
isOpaque = opaque
}
@@ -63,4 +64,25 @@ class LightRevealScrimTest : SysuiTestCase() {
scrim.revealAmount = 0.5f
assertFalse("Scrim is opaque even though it's revealed", scrim.isScrimOpaque)
}
@Test
fun testBeforeOnMeasure_defaultDimensions() {
assertThat(scrim.viewWidth).isEqualTo(DEFAULT_WIDTH)
assertThat(scrim.viewHeight).isEqualTo(DEFAULT_HEIGHT)
}
@Test
fun testAfterOnMeasure_measuredDimensions() {
scrim.measure(/* widthMeasureSpec= */ exact(1), /* heightMeasureSpec= */ exact(2))
assertThat(scrim.viewWidth).isEqualTo(1)
assertThat(scrim.viewHeight).isEqualTo(2)
}
private fun exact(value: Int) = View.MeasureSpec.makeMeasureSpec(value, View.MeasureSpec.EXACTLY)
private companion object {
private const val DEFAULT_WIDTH = 42
private const val DEFAULT_HEIGHT = 24
}
}