summaryrefslogtreecommitdiff
path: root/graphics/java/android
diff options
context:
space:
mode:
author Lucas Dupin <dupin@google.com> 2021-03-15 23:45:33 -0700
committer Lucas Dupin <dupin@google.com> 2021-03-15 23:47:58 -0700
commitb9610108d5b8e5ed9908071c8a07587e1cab8ea7 (patch)
treeca64f97196ead14afd54f00c92aeb949f937f40f /graphics/java/android
parentc7a5fdd81c2d6da97bd98b46be7451f5f062f2a5 (diff)
Fix issue where ripple would move
The correct behavior is for the circle to move inside the RenderNode bounds. The RenderNode itself should not move at all. Fixes: 182174260 Test: visual Change-Id: I254138cada2586312530122fcb9ba4518d864cdf
Diffstat (limited to 'graphics/java/android')
-rw-r--r--graphics/java/android/graphics/drawable/RippleAnimationSession.java45
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java8
-rw-r--r--graphics/java/android/graphics/drawable/RippleShader.java10
3 files changed, 20 insertions, 43 deletions
diff --git a/graphics/java/android/graphics/drawable/RippleAnimationSession.java b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
index f3bf63bb3660..877d07f0d928 100644
--- a/graphics/java/android/graphics/drawable/RippleAnimationSession.java
+++ b/graphics/java/android/graphics/drawable/RippleAnimationSession.java
@@ -38,8 +38,7 @@ import java.util.function.Consumer;
*/
public final class RippleAnimationSession {
private static final String TAG = "RippleAnimationSession";
- private static final int ENTER_ANIM_DURATION = 300;
- private static final int SLIDE_ANIM_DURATION = 450;
+ private static final int ENTER_ANIM_DURATION = 450;
private static final int EXIT_ANIM_DURATION = 300;
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
private static final TimeInterpolator PATH_INTERPOLATOR =
@@ -50,16 +49,13 @@ public final class RippleAnimationSession {
private Runnable mOnUpdate;
private long mStartTime;
private boolean mForceSoftware;
- private final float mWidth, mHeight;
private final ValueAnimator mSparkle = ValueAnimator.ofFloat(0, 1);
private final ArraySet<Animator> mActiveAnimations = new ArraySet<>(3);
RippleAnimationSession(@NonNull AnimationProperties<Float, Paint> properties,
- boolean forceSoftware, float width, float height) {
+ boolean forceSoftware) {
mProperties = properties;
mForceSoftware = forceSoftware;
- mWidth = width;
- mHeight = height;
mSparkle.addUpdateListener(anim -> {
final long now = AnimationUtils.currentAnimationTimeMillis();
@@ -134,7 +130,7 @@ public final class RippleAnimationSession {
private long computeDelay() {
final long timePassed = AnimationUtils.currentAnimationTimeMillis() - mStartTime;
- return Math.max((long) SLIDE_ANIM_DURATION - timePassed, 0);
+ return Math.max((long) ENTER_ANIM_DURATION - timePassed, 0);
}
private void notifyUpdate() {
@@ -175,54 +171,29 @@ public final class RippleAnimationSession {
props = getCanvasProperties();
RenderNodeAnimator expand =
new RenderNodeAnimator(props.getProgress(), .5f);
- RenderNodeAnimator slideX =
- new RenderNodeAnimator(props.getX(), mWidth / 2);
- RenderNodeAnimator slideY =
- new RenderNodeAnimator(props.getY(), mHeight / 2);
expand.setTarget(canvas);
- slideX.setTarget(canvas);
- slideY.setTarget(canvas);
- startAnimation(expand, slideX, slideY);
+ startAnimation(expand);
}
- private void startAnimation(Animator expand,
- Animator slideX, Animator slideY) {
- expand.setDuration(SLIDE_ANIM_DURATION);
- slideX.setDuration(SLIDE_ANIM_DURATION);
- slideY.setDuration(SLIDE_ANIM_DURATION);
- slideX.addListener(new AnimatorListener(this));
+ private void startAnimation(Animator expand) {
+ expand.setDuration(ENTER_ANIM_DURATION);
+ expand.addListener(new AnimatorListener(this));
expand.setInterpolator(LINEAR_INTERPOLATOR);
- slideX.setInterpolator(PATH_INTERPOLATOR);
- slideY.setInterpolator(PATH_INTERPOLATOR);
expand.start();
- slideX.start();
- slideY.start();
if (!mSparkle.isRunning()) {
mSparkle.start();
mActiveAnimations.add(mSparkle);
}
mActiveAnimations.add(expand);
- mActiveAnimations.add(slideX);
- mActiveAnimations.add(slideY);
}
private void enterSoftware() {
ValueAnimator expand = ValueAnimator.ofFloat(0f, 0.5f);
- ValueAnimator slideX = ValueAnimator.ofFloat(
- mProperties.getX(), mWidth / 2);
- ValueAnimator slideY = ValueAnimator.ofFloat(
- mProperties.getY(), mHeight / 2);
expand.addUpdateListener(updatedAnimation -> {
notifyUpdate();
mProperties.getShader().setProgress((Float) expand.getAnimatedValue());
});
- slideX.addUpdateListener(anim -> {
- float x = (float) slideX.getAnimatedValue();
- float y = (float) slideY.getAnimatedValue();
- mProperties.setOrigin(x, y);
- mProperties.getShader().setOrigin(x, y);
- });
- startAnimation(expand, slideX, slideY);
+ startAnimation(expand);
}
@NonNull AnimationProperties<Float, Paint> getProperties() {
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index d6bbee90d73b..c6d996234fb3 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -842,7 +842,7 @@ public class RippleDrawable extends LayerDrawable {
if (shouldAnimate && mRunningAnimations.size() <= MAX_RIPPLES) {
RippleAnimationSession.AnimationProperties<Float, Paint> properties =
createAnimationProperties(x, y, w, h);
- mRunningAnimations.add(new RippleAnimationSession(properties, !useCanvasProps, w, h)
+ mRunningAnimations.add(new RippleAnimationSession(properties, !useCanvasProps)
.setOnAnimationUpdated(() -> invalidateSelf(false))
.setOnSessionEnd(session -> {
mRunningAnimations.remove(session);
@@ -912,14 +912,14 @@ public class RippleDrawable extends LayerDrawable {
? mState.mColor.getColorForState(getState(), Color.BLACK)
: mMaskColorFilter.getColor();
shader.setColor(color);
- shader.setOrigin(x, y);
+ shader.setOrigin(w / 2, y / 2);
+ shader.setTouch(x, y);
shader.setResolution(w, h);
shader.setSecondsOffset(0);
shader.setRadius(radius);
shader.setProgress(.0f);
properties = new RippleAnimationSession.AnimationProperties<>(
- x, y, radius, p, 0f,
- shader);
+ w / 2, h / 2, radius, p, 0f, shader);
if (mMaskShader == null) {
shader.setShader(null);
} else {
diff --git a/graphics/java/android/graphics/drawable/RippleShader.java b/graphics/java/android/graphics/drawable/RippleShader.java
index 657a32c1ac46..8eddbea4d1f8 100644
--- a/graphics/java/android/graphics/drawable/RippleShader.java
+++ b/graphics/java/android/graphics/drawable/RippleShader.java
@@ -23,6 +23,7 @@ import android.graphics.Shader;
final class RippleShader extends RuntimeShader {
private static final String SHADER_UNIFORMS = "uniform vec2 in_origin;\n"
+ + "uniform vec2 in_touch;\n"
+ "uniform float in_progress;\n"
+ "uniform float in_maxRadius;\n"
+ "uniform vec2 in_resolution;\n"
@@ -79,12 +80,13 @@ final class RippleShader extends RuntimeShader {
+ " float fadeIn = subProgress(0., 0.175, in_progress);\n"
+ " float fadeOutNoise = subProgress(0.375, 1., in_progress);\n"
+ " float fadeOutRipple = subProgress(0.375, 0.75, in_progress);\n"
- + " float ring = getRingMask(p, in_origin, in_maxRadius, fadeIn);\n"
+ + " vec2 center = mix(in_touch, in_origin, fadeIn);\n"
+ + " float ring = getRingMask(p, center, in_maxRadius, fadeIn);\n"
+ " float alpha = min(fadeIn, 1. - fadeOutNoise);\n"
+ " float sparkle = sparkles(p, in_progress * 0.25 + in_secondsOffset)\n"
+ " * ring * alpha;\n"
+ " float fade = min(fadeIn, 1.-fadeOutRipple);\n"
- + " vec4 circle = in_color * (softCircle(p, in_origin, in_maxRadius "
+ + " vec4 circle = in_color * (softCircle(p, center, in_maxRadius "
+ " * fadeIn, 0.2) * fade);\n"
+ " float mask = in_hasMask == 1. ? sample(in_shader).a > 0. ? 1. : 0. : 1.;\n"
+ " return mix(circle, vec4(sparkle), sparkle) * mask;\n"
@@ -117,6 +119,10 @@ final class RippleShader extends RuntimeShader {
setUniform("in_origin", new float[] {x, y});
}
+ public void setTouch(float x, float y) {
+ setUniform("in_touch", new float[] {x, y});
+ }
+
public void setProgress(float progress) {
setUniform("in_progress", progress);
}