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

Commit 6a731c2c authored by Yein Jo's avatar Yein Jo
Browse files

Update uniform params for the tablet docking animation.

Please find the recordings in the bug attached.

Bug: 269124200
Test: Manual
Test: adb shell cmd statusbar docking-ripple
Change-Id: I31f7baf272f67be4ab85b3e35fd0a0269cf0e0ed
parent fabc17ea
Loading
Loading
Loading
Loading
+87 −2
Original line number Diff line number Diff line
@@ -80,6 +80,87 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
        ripplePaint.shader = rippleShader
    }

    /**
     * Sets the fade parameters for the base ring.
     *
     * <p>Base ring indicates a blurred ring below the sparkle ring. See
     * [RippleShader.baseRingFadeParams].
     */
    @JvmOverloads
    fun setBaseRingFadeParams(
        fadeInStart: Float = rippleShader.baseRingFadeParams.fadeInStart,
        fadeInEnd: Float = rippleShader.baseRingFadeParams.fadeInEnd,
        fadeOutStart: Float = rippleShader.baseRingFadeParams.fadeOutStart,
        fadeOutEnd: Float = rippleShader.baseRingFadeParams.fadeOutEnd
    ) {
        setFadeParams(
            rippleShader.baseRingFadeParams,
            fadeInStart,
            fadeInEnd,
            fadeOutStart,
            fadeOutEnd
        )
    }

    /**
     * Sets the fade parameters for the sparkle ring.
     *
     * <p>Sparkle ring refers to the ring that's drawn on top of the base ring. See
     * [RippleShader.sparkleRingFadeParams].
     */
    @JvmOverloads
    fun setSparkleRingFadeParams(
        fadeInStart: Float = rippleShader.sparkleRingFadeParams.fadeInStart,
        fadeInEnd: Float = rippleShader.sparkleRingFadeParams.fadeInEnd,
        fadeOutStart: Float = rippleShader.sparkleRingFadeParams.fadeOutStart,
        fadeOutEnd: Float = rippleShader.sparkleRingFadeParams.fadeOutEnd
    ) {
        setFadeParams(
            rippleShader.sparkleRingFadeParams,
            fadeInStart,
            fadeInEnd,
            fadeOutStart,
            fadeOutEnd
        )
    }

    /**
     * Sets the fade parameters for the center fill.
     *
     * <p>One common use case is set all the params to 1, which completely removes the center fill.
     * See [RippleShader.centerFillFadeParams].
     */
    @JvmOverloads
    fun setCenterFillFadeParams(
        fadeInStart: Float = rippleShader.centerFillFadeParams.fadeInStart,
        fadeInEnd: Float = rippleShader.centerFillFadeParams.fadeInEnd,
        fadeOutStart: Float = rippleShader.centerFillFadeParams.fadeOutStart,
        fadeOutEnd: Float = rippleShader.centerFillFadeParams.fadeOutEnd
    ) {
        setFadeParams(
            rippleShader.centerFillFadeParams,
            fadeInStart,
            fadeInEnd,
            fadeOutStart,
            fadeOutEnd
        )
    }

    private fun setFadeParams(
        fadeParams: RippleShader.FadeParams,
        fadeInStart: Float,
        fadeInEnd: Float,
        fadeOutStart: Float,
        fadeOutEnd: Float
    ) {
        with(fadeParams) {
            this.fadeInStart = fadeInStart
            this.fadeInEnd = fadeInEnd
            this.fadeOutStart = fadeOutStart
            this.fadeOutEnd = fadeOutEnd
        }
    }

    /**
     * Sets blur multiplier at start and end of the progress.
     *
@@ -148,11 +229,11 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
        }
        // To reduce overdraw, we mask the effect to a circle or a rectangle that's bigger than the
        // active effect area. Values here should be kept in sync with the animation implementation
        // in the ripple shader. (Twice bigger)
        // in the ripple shader.
        if (rippleShape == RippleShape.CIRCLE) {
            val maskRadius = rippleShader.rippleSize.currentWidth
            canvas.drawCircle(centerX, centerY, maskRadius, ripplePaint)
        } else {
        } else if (rippleShape == RippleShape.ELLIPSE) {
            val maskWidth = rippleShader.rippleSize.currentWidth * 2
            val maskHeight = rippleShader.rippleSize.currentHeight * 2
            canvas.drawRect(
@@ -162,6 +243,10 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
                /* bottom= */ centerY + maskHeight,
                ripplePaint
            )
        } else { // RippleShape.RoundedBox
            // No masking for the rounded box, as it has more blur which requires larger bounds.
            // Masking creates sharp bounds even when the masking is 4 times bigger.
            canvas.drawPaint(ripplePaint)
        }
    }
}
+75 −19
Original line number Diff line number Diff line
@@ -33,7 +33,9 @@ import android.widget.TextView;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
import com.android.systemui.surfaceeffects.ripple.RippleShader;
import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
import com.android.systemui.surfaceeffects.ripple.RippleView;

@@ -44,10 +46,12 @@ import java.text.NumberFormat;
 */
final class WirelessChargingLayout extends FrameLayout {
    private static final long CIRCLE_RIPPLE_ANIMATION_DURATION = 1500;
    private static final long ROUNDED_BOX_RIPPLE_ANIMATION_DURATION = 1750;
    private static final long ROUNDED_BOX_RIPPLE_ANIMATION_DURATION = 3000;
    private static final int SCRIM_COLOR = 0x4C000000;
    private static final int SCRIM_FADE_DURATION = 300;
    private RippleView mRippleView;
    // This is only relevant to the rounded box ripple.
    private RippleShader.SizeAtProgress[] mSizeAtProgressArray;

    WirelessChargingLayout(Context context, int transmittingBatteryLevel, int batteryLevel,
            boolean isDozing, RippleShape rippleShape) {
@@ -125,6 +129,8 @@ final class WirelessChargingLayout extends FrameLayout {
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);

        // For tablet docking animation, we don't play the background scrim.
        if (!Utilities.isTablet(context)) {
            ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
                    "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
            scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
@@ -139,6 +145,7 @@ final class WirelessChargingLayout extends FrameLayout {
            AnimatorSet animatorSetScrim = new AnimatorSet();
            animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator);
            animatorSetScrim.start();
        }

        mRippleView = findViewById(R.id.wireless_charging_ripple);
        mRippleView.setupShader(rippleShape);
@@ -147,7 +154,26 @@ final class WirelessChargingLayout extends FrameLayout {
        if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
            mRippleView.setDuration(ROUNDED_BOX_RIPPLE_ANIMATION_DURATION);
            mRippleView.setSparkleStrength(0.22f);
            mRippleView.setColor(color, 28);
            mRippleView.setColor(color, 102); // 40% of opacity.
            mRippleView.setBaseRingFadeParams(
                    /* fadeInStart = */ 0f,
                    /* fadeInEnd = */ 0f,
                    /* fadeOutStart = */ 0.2f,
                    /* fadeOutEnd= */ 0.47f
            );
            mRippleView.setSparkleRingFadeParams(
                    /* fadeInStart = */ 0f,
                    /* fadeInEnd = */ 0f,
                    /* fadeOutStart = */ 0.2f,
                    /* fadeOutEnd= */ 1f
            );
            mRippleView.setCenterFillFadeParams(
                    /* fadeInStart = */ 0f,
                    /* fadeInEnd = */ 0f,
                    /* fadeOutStart = */ 0f,
                    /* fadeOutEnd= */ 0.2f
            );
            mRippleView.setBlur(6.5f, 2.5f);
        } else {
            mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
            mRippleView.setColor(color, RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA);
@@ -246,9 +272,7 @@ final class WirelessChargingLayout extends FrameLayout {
            int height = getMeasuredHeight();
            mRippleView.setCenter(width * 0.5f, height * 0.5f);
            if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
                // Those magic numbers are introduced for visual polish. This aspect ratio maps with
                // the tablet's docking station.
                mRippleView.setMaxSize(width * 1.36f, height * 1.46f);
                updateRippleSizeAtProgressList(width, height);
            } else {
                float maxSize = Math.max(width, height);
                mRippleView.setMaxSize(maxSize, maxSize);
@@ -257,4 +281,36 @@ final class WirelessChargingLayout extends FrameLayout {

        super.onLayout(changed, left, top, right, bottom);
    }

    private void updateRippleSizeAtProgressList(float width, float height) {
        if (mSizeAtProgressArray == null) {
            float maxSize = Math.max(width, height);
            mSizeAtProgressArray = new RippleShader.SizeAtProgress[] {
                    // Those magic numbers are introduced for visual polish. It starts from a pill
                    // shape and expand to a full circle.
                    new RippleShader.SizeAtProgress(0f, 0f, 0f),
                    new RippleShader.SizeAtProgress(0.3f, width * 0.4f, height * 0.4f),
                    new RippleShader.SizeAtProgress(1f, maxSize, maxSize)
            };
        } else {
            // Same multipliers, just need to recompute with the new width and height.
            RippleShader.SizeAtProgress first = mSizeAtProgressArray[0];
            first.setT(0f);
            first.setWidth(0f);
            first.setHeight(0f);

            RippleShader.SizeAtProgress second = mSizeAtProgressArray[1];
            second.setT(0.3f);
            second.setWidth(width * 0.4f);
            second.setHeight(height * 0.4f);

            float maxSize = Math.max(width, height);
            RippleShader.SizeAtProgress last = mSizeAtProgressArray[2];
            last.setT(1f);
            last.setWidth(maxSize);
            last.setHeight(maxSize);
        }

        mRippleView.setSizeAtProgresses(mSizeAtProgressArray);
    }
}