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
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,20 +129,23 @@ final class WirelessChargingLayout extends FrameLayout {
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);
|
||||
|
||||
ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
|
||||
"backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
|
||||
scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
|
||||
scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR);
|
||||
ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this,
|
||||
"backgroundColor", SCRIM_COLOR, Color.TRANSPARENT);
|
||||
scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION);
|
||||
scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR);
|
||||
scrimFadeOutAnimator.setStartDelay((rippleShape == RippleShape.CIRCLE
|
||||
? CIRCLE_RIPPLE_ANIMATION_DURATION : ROUNDED_BOX_RIPPLE_ANIMATION_DURATION)
|
||||
- SCRIM_FADE_DURATION);
|
||||
AnimatorSet animatorSetScrim = new AnimatorSet();
|
||||
animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator);
|
||||
animatorSetScrim.start();
|
||||
// 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);
|
||||
scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR);
|
||||
ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this,
|
||||
"backgroundColor", SCRIM_COLOR, Color.TRANSPARENT);
|
||||
scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION);
|
||||
scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR);
|
||||
scrimFadeOutAnimator.setStartDelay((rippleShape == RippleShape.CIRCLE
|
||||
? CIRCLE_RIPPLE_ANIMATION_DURATION : ROUNDED_BOX_RIPPLE_ANIMATION_DURATION)
|
||||
- SCRIM_FADE_DURATION);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user