Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d976bb4a authored by Nicolo' Mazzucato's avatar Nicolo' Mazzucato
Browse files

Fix flicker when starting folding

The dimensions of LightRevealScrim were used before the view was being measured, causing the entire screen to become black for one frame sometimes (especially after boot.

Now, LightRevealScrim accepts the initial dimensions what are used before the view is measured.

Bug: 261560634
Test: LightRevealScrimTest && many unfolds soon after rebooting
Change-Id: I91d1f2de82c563f085c9565c6e7116abb1e43e1d
parent 2ea53262
Loading
Loading
Loading
Loading
+37 −9
Original line number Diff line number Diff line
@@ -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
+16 −10
Original line number Diff line number Diff line
@@ -159,8 +159,15 @@ constructor(
        ensureOverlayRemoved()

        val newRoot = SurfaceControlViewHost(context, context.display!!, wwm)
        val params = getLayoutParams()
        val newView =
            LightRevealScrim(context, null).apply {
            LightRevealScrim(
                    context,
                    attrs = null,
                    initialWidth = params.width,
                    initialHeight = params.height
                )
                .apply {
                    revealEffect = createLightRevealEffect()
                    isScrimOpaqueChangedListener = Consumer {}
                    revealAmount =
@@ -170,7 +177,6 @@ constructor(
                        }
                }

        val params = getLayoutParams()
        newRoot.setView(newView, params)

        if (onOverlayReady != null) {
+23 −1
Original line number Diff line number Diff line
@@ -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
  }
}
 No newline at end of file