Loading graphics/java/android/graphics/drawable/RippleComponent.java +4 −10 Original line number Diff line number Diff line Loading @@ -69,7 +69,6 @@ abstract class RippleComponent { mDensity = density; onSetup(); onTargetRadiusChanged(mTargetRadius); } Loading @@ -82,8 +81,11 @@ abstract class RippleComponent { cancel(); mSoftwareAnimator = createSoftwareEnter(fast); if (mSoftwareAnimator != null) { mSoftwareAnimator.start(); } } /** * Starts a ripple exit animation. Loading Loading @@ -250,14 +252,6 @@ abstract class RippleComponent { // Stub. } /** * Called during ripple setup, which occurs before the first enter * animation. */ protected void onSetup() { // Stub. } protected abstract Animator createSoftwareEnter(boolean fast); protected abstract Animator createSoftwareExit(); Loading graphics/java/android/graphics/drawable/RippleDrawable.java +3 −1 Original line number Diff line number Diff line Loading @@ -564,7 +564,9 @@ public class RippleDrawable extends LayerDrawable { x = mHotspotBounds.exactCenterX(); y = mHotspotBounds.exactCenterY(); } mRipple = new RippleForeground(this, mHotspotBounds, x, y); final boolean isBounded = !isProjected(); mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded); } mRipple.setup(mState.mMaxRadius, mDensity); Loading graphics/java/android/graphics/drawable/RippleForeground.java +137 −48 Original line number Diff line number Diff line Loading @@ -44,9 +44,16 @@ class RippleForeground extends RippleComponent { private static final float WAVE_TOUCH_UP_ACCELERATION = 3400; private static final float WAVE_OPACITY_DECAY_VELOCITY = 3; // Bounded ripple animation properties. private static final int BOUNDED_ORIGIN_EXIT_DURATION = 300; private static final int BOUNDED_RADIUS_EXIT_DURATION = 800; private static final int BOUNDED_OPACITY_EXIT_DURATION = 400; private static final float MAX_BOUNDED_RADIUS = 350; private static final int RIPPLE_ENTER_DELAY = 80; private static final int OPACITY_ENTER_DURATION_FAST = 120; // Parent-relative values for starting position. private float mStartingX; private float mStartingY; private float mClampedStartingX; Loading @@ -58,30 +65,41 @@ class RippleForeground extends RippleComponent { private CanvasProperty<Float> mPropX; private CanvasProperty<Float> mPropY; // Target values for tween animations. private float mTargetX = 0; private float mTargetY = 0; /** Ripple target radius used when bounded. Not used for clamping. */ private float mBoundedRadius = 0; // Software rendering properties. private float mOpacity = 1; private float mOuterX; private float mOuterY; // Values used to tween between the start and end positions. private float mTweenRadius = 0; private float mTweenX = 0; private float mTweenY = 0; /** Whether this ripple is bounded. */ private boolean mIsBounded; /** Whether this ripple has finished its exit animation. */ private boolean mHasFinishedExit; public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY) { public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY, boolean isBounded) { super(owner, bounds); mIsBounded = isBounded; mStartingX = startingX; mStartingY = startingY; } @Override public void onSetup() { mOuterX = 0; mOuterY = 0; if (isBounded) { mBoundedRadius = MAX_BOUNDED_RADIUS * 0.9f + (float) (MAX_BOUNDED_RADIUS * Math.random() * 0.1); } else { mBoundedRadius = 0; } } @Override Loading @@ -95,12 +113,10 @@ class RippleForeground extends RippleComponent { final int origAlpha = p.getAlpha(); final int alpha = (int) (origAlpha * mOpacity + 0.5f); final float radius = MathUtils.lerp(0, mTargetRadius, mTweenRadius); final float radius = getCurrentRadius(); if (alpha > 0 && radius > 0) { final float x = MathUtils.lerp( mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX); final float y = MathUtils.lerp( mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY); final float x = getCurrentX(); final float y = getCurrentY(); p.setAlpha(alpha); c.drawCircle(x, y, radius, p); p.setAlpha(origAlpha); Loading @@ -120,8 +136,8 @@ class RippleForeground extends RippleComponent { * Returns the maximum bounds of the ripple relative to the ripple center. */ public void getBounds(Rect bounds) { final int outerX = (int) mOuterX; final int outerY = (int) mOuterY; final int outerX = (int) mTargetX; final int outerY = (int) mTargetY; final int r = (int) mTargetRadius + 1; bounds.set(outerX - r, outerY - r, outerX + r, outerY + r); } Loading @@ -146,14 +162,25 @@ class RippleForeground extends RippleComponent { @Override protected Animator createSoftwareEnter(boolean fast) { // Bounded ripples don't have enter animations. if (mIsBounded) { return null; } final int duration = (int) (1000 * Math.sqrt(mTargetRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5); final ObjectAnimator tweenAll = ObjectAnimator.ofFloat(this, TWEEN_ALL, 1); tweenAll.setAutoCancel(true); tweenAll.setDuration(duration); tweenAll.setInterpolator(LINEAR_INTERPOLATOR); tweenAll.setStartDelay(RIPPLE_ENTER_DELAY); final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); tweenRadius.setAutoCancel(true); tweenRadius.setDuration(duration); tweenRadius.setInterpolator(LINEAR_INTERPOLATOR); tweenRadius.setStartDelay(RIPPLE_ENTER_DELAY); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); tweenOrigin.setAutoCancel(true); tweenOrigin.setDuration(duration); tweenOrigin.setInterpolator(LINEAR_INTERPOLATOR); tweenOrigin.setStartDelay(RIPPLE_ENTER_DELAY); final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 1); opacity.setAutoCancel(true); Loading @@ -161,31 +188,68 @@ class RippleForeground extends RippleComponent { opacity.setInterpolator(LINEAR_INTERPOLATOR); final AnimatorSet set = new AnimatorSet(); set.play(tweenAll).with(opacity); set.play(tweenOrigin).with(tweenRadius).with(opacity); return set; } private float getCurrentX() { return MathUtils.lerp(mClampedStartingX - mBounds.exactCenterX(), mTargetX, mTweenX); } private float getCurrentY() { return MathUtils.lerp(mClampedStartingY - mBounds.exactCenterY(), mTargetY, mTweenY); } private int getRadiusExitDuration() { final float radius = MathUtils.lerp(0, mTargetRadius, mTweenRadius); final float remaining = mTargetRadius - radius; return (int) (1000 * Math.sqrt(remaining / (WAVE_TOUCH_UP_ACCELERATION final float remainingRadius = mTargetRadius - getCurrentRadius(); return (int) (1000 * Math.sqrt(remainingRadius / (WAVE_TOUCH_UP_ACCELERATION + WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5); } private float getCurrentRadius() { return MathUtils.lerp(0, mTargetRadius, mTweenRadius); } private int getOpacityExitDuration() { return (int) (1000 * mOpacity / WAVE_OPACITY_DECAY_VELOCITY + 0.5f); } /** * Compute target values that are dependent on bounding. */ private void computeBoundedTargetValues() { mTargetX = (mClampedStartingX - mBounds.exactCenterX()) * .7f; mTargetY = (mClampedStartingY - mBounds.exactCenterY()) * .7f; mTargetRadius = mBoundedRadius; } @Override protected Animator createSoftwareExit() { final int radiusDuration = getRadiusExitDuration(); final int opacityDuration = getOpacityExitDuration(); final int radiusDuration; final int originDuration; final int opacityDuration; if (mIsBounded) { computeBoundedTargetValues(); radiusDuration = BOUNDED_RADIUS_EXIT_DURATION; originDuration = BOUNDED_ORIGIN_EXIT_DURATION; opacityDuration = BOUNDED_OPACITY_EXIT_DURATION; } else { radiusDuration = getRadiusExitDuration(); originDuration = radiusDuration; opacityDuration = getOpacityExitDuration(); } final ObjectAnimator tweenAll = ObjectAnimator.ofFloat(this, TWEEN_ALL, 1); tweenAll.setAutoCancel(true); tweenAll.setDuration(radiusDuration); tweenAll.setInterpolator(DECELERATE_INTERPOLATOR); final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); tweenRadius.setAutoCancel(true); tweenRadius.setDuration(radiusDuration); tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); tweenOrigin.setAutoCancel(true); tweenOrigin.setDuration(originDuration); tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR); final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 0); opacity.setAutoCancel(true); Loading @@ -193,7 +257,7 @@ class RippleForeground extends RippleComponent { opacity.setInterpolator(LINEAR_INTERPOLATOR); final AnimatorSet set = new AnimatorSet(); set.play(tweenAll).with(opacity); set.play(tweenOrigin).with(tweenRadius).with(opacity); set.addListener(mAnimationListener); return set; Loading @@ -201,15 +265,25 @@ class RippleForeground extends RippleComponent { @Override protected RenderNodeAnimatorSet createHardwareExit(Paint p) { final int radiusDuration = getRadiusExitDuration(); final int opacityDuration = getOpacityExitDuration(); final int radiusDuration; final int originDuration; final int opacityDuration; if (mIsBounded) { computeBoundedTargetValues(); radiusDuration = BOUNDED_RADIUS_EXIT_DURATION; originDuration = BOUNDED_ORIGIN_EXIT_DURATION; opacityDuration = BOUNDED_OPACITY_EXIT_DURATION; } else { radiusDuration = getRadiusExitDuration(); originDuration = radiusDuration; opacityDuration = getOpacityExitDuration(); } final float startX = MathUtils.lerp( mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX); final float startY = MathUtils.lerp( mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY); final float startX = getCurrentX(); final float startY = getCurrentY(); final float startRadius = getCurrentRadius(); final float startRadius = MathUtils.lerp(0, mTargetRadius, mTweenRadius); p.setAlpha((int) (p.getAlpha() * mOpacity + 0.5f)); mPropPaint = CanvasProperty.createPaint(p); Loading @@ -221,12 +295,12 @@ class RippleForeground extends RippleComponent { radius.setDuration(radiusDuration); radius.setInterpolator(DECELERATE_INTERPOLATOR); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mOuterX); x.setDuration(radiusDuration); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX); x.setDuration(originDuration); x.setInterpolator(DECELERATE_INTERPOLATOR); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mOuterY); y.setDuration(radiusDuration); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY); y.setDuration(originDuration); y.setInterpolator(DECELERATE_INTERPOLATOR); final RenderNodeAnimator opacity = new RenderNodeAnimator(mPropPaint, Loading Loading @@ -307,14 +381,29 @@ class RippleForeground extends RippleComponent { } /** * Property for animating radius, center X, and center Y between their * initial and target values. * Property for animating radius between its initial and target values. */ private static final FloatProperty<RippleForeground> TWEEN_ALL = new FloatProperty<RippleForeground>("tweenAll") { private static final FloatProperty<RippleForeground> TWEEN_RADIUS = new FloatProperty<RippleForeground>("tweenRadius") { @Override public void setValue(RippleForeground object, float value) { object.mTweenRadius = value; object.invalidateSelf(); } @Override public Float get(RippleForeground object) { return object.mTweenRadius; } }; /** * Property for animating origin between its initial and target values. */ private static final FloatProperty<RippleForeground> TWEEN_ORIGIN = new FloatProperty<RippleForeground>("tweenOrigin") { @Override public void setValue(RippleForeground object, float value) { object.mTweenX = value; object.mTweenY = value; object.invalidateSelf(); Loading @@ -322,7 +411,7 @@ class RippleForeground extends RippleComponent { @Override public Float get(RippleForeground object) { return object.mTweenRadius; return object.mTweenX; } }; Loading Loading
graphics/java/android/graphics/drawable/RippleComponent.java +4 −10 Original line number Diff line number Diff line Loading @@ -69,7 +69,6 @@ abstract class RippleComponent { mDensity = density; onSetup(); onTargetRadiusChanged(mTargetRadius); } Loading @@ -82,8 +81,11 @@ abstract class RippleComponent { cancel(); mSoftwareAnimator = createSoftwareEnter(fast); if (mSoftwareAnimator != null) { mSoftwareAnimator.start(); } } /** * Starts a ripple exit animation. Loading Loading @@ -250,14 +252,6 @@ abstract class RippleComponent { // Stub. } /** * Called during ripple setup, which occurs before the first enter * animation. */ protected void onSetup() { // Stub. } protected abstract Animator createSoftwareEnter(boolean fast); protected abstract Animator createSoftwareExit(); Loading
graphics/java/android/graphics/drawable/RippleDrawable.java +3 −1 Original line number Diff line number Diff line Loading @@ -564,7 +564,9 @@ public class RippleDrawable extends LayerDrawable { x = mHotspotBounds.exactCenterX(); y = mHotspotBounds.exactCenterY(); } mRipple = new RippleForeground(this, mHotspotBounds, x, y); final boolean isBounded = !isProjected(); mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded); } mRipple.setup(mState.mMaxRadius, mDensity); Loading
graphics/java/android/graphics/drawable/RippleForeground.java +137 −48 Original line number Diff line number Diff line Loading @@ -44,9 +44,16 @@ class RippleForeground extends RippleComponent { private static final float WAVE_TOUCH_UP_ACCELERATION = 3400; private static final float WAVE_OPACITY_DECAY_VELOCITY = 3; // Bounded ripple animation properties. private static final int BOUNDED_ORIGIN_EXIT_DURATION = 300; private static final int BOUNDED_RADIUS_EXIT_DURATION = 800; private static final int BOUNDED_OPACITY_EXIT_DURATION = 400; private static final float MAX_BOUNDED_RADIUS = 350; private static final int RIPPLE_ENTER_DELAY = 80; private static final int OPACITY_ENTER_DURATION_FAST = 120; // Parent-relative values for starting position. private float mStartingX; private float mStartingY; private float mClampedStartingX; Loading @@ -58,30 +65,41 @@ class RippleForeground extends RippleComponent { private CanvasProperty<Float> mPropX; private CanvasProperty<Float> mPropY; // Target values for tween animations. private float mTargetX = 0; private float mTargetY = 0; /** Ripple target radius used when bounded. Not used for clamping. */ private float mBoundedRadius = 0; // Software rendering properties. private float mOpacity = 1; private float mOuterX; private float mOuterY; // Values used to tween between the start and end positions. private float mTweenRadius = 0; private float mTweenX = 0; private float mTweenY = 0; /** Whether this ripple is bounded. */ private boolean mIsBounded; /** Whether this ripple has finished its exit animation. */ private boolean mHasFinishedExit; public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY) { public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY, boolean isBounded) { super(owner, bounds); mIsBounded = isBounded; mStartingX = startingX; mStartingY = startingY; } @Override public void onSetup() { mOuterX = 0; mOuterY = 0; if (isBounded) { mBoundedRadius = MAX_BOUNDED_RADIUS * 0.9f + (float) (MAX_BOUNDED_RADIUS * Math.random() * 0.1); } else { mBoundedRadius = 0; } } @Override Loading @@ -95,12 +113,10 @@ class RippleForeground extends RippleComponent { final int origAlpha = p.getAlpha(); final int alpha = (int) (origAlpha * mOpacity + 0.5f); final float radius = MathUtils.lerp(0, mTargetRadius, mTweenRadius); final float radius = getCurrentRadius(); if (alpha > 0 && radius > 0) { final float x = MathUtils.lerp( mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX); final float y = MathUtils.lerp( mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY); final float x = getCurrentX(); final float y = getCurrentY(); p.setAlpha(alpha); c.drawCircle(x, y, radius, p); p.setAlpha(origAlpha); Loading @@ -120,8 +136,8 @@ class RippleForeground extends RippleComponent { * Returns the maximum bounds of the ripple relative to the ripple center. */ public void getBounds(Rect bounds) { final int outerX = (int) mOuterX; final int outerY = (int) mOuterY; final int outerX = (int) mTargetX; final int outerY = (int) mTargetY; final int r = (int) mTargetRadius + 1; bounds.set(outerX - r, outerY - r, outerX + r, outerY + r); } Loading @@ -146,14 +162,25 @@ class RippleForeground extends RippleComponent { @Override protected Animator createSoftwareEnter(boolean fast) { // Bounded ripples don't have enter animations. if (mIsBounded) { return null; } final int duration = (int) (1000 * Math.sqrt(mTargetRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5); final ObjectAnimator tweenAll = ObjectAnimator.ofFloat(this, TWEEN_ALL, 1); tweenAll.setAutoCancel(true); tweenAll.setDuration(duration); tweenAll.setInterpolator(LINEAR_INTERPOLATOR); tweenAll.setStartDelay(RIPPLE_ENTER_DELAY); final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); tweenRadius.setAutoCancel(true); tweenRadius.setDuration(duration); tweenRadius.setInterpolator(LINEAR_INTERPOLATOR); tweenRadius.setStartDelay(RIPPLE_ENTER_DELAY); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); tweenOrigin.setAutoCancel(true); tweenOrigin.setDuration(duration); tweenOrigin.setInterpolator(LINEAR_INTERPOLATOR); tweenOrigin.setStartDelay(RIPPLE_ENTER_DELAY); final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 1); opacity.setAutoCancel(true); Loading @@ -161,31 +188,68 @@ class RippleForeground extends RippleComponent { opacity.setInterpolator(LINEAR_INTERPOLATOR); final AnimatorSet set = new AnimatorSet(); set.play(tweenAll).with(opacity); set.play(tweenOrigin).with(tweenRadius).with(opacity); return set; } private float getCurrentX() { return MathUtils.lerp(mClampedStartingX - mBounds.exactCenterX(), mTargetX, mTweenX); } private float getCurrentY() { return MathUtils.lerp(mClampedStartingY - mBounds.exactCenterY(), mTargetY, mTweenY); } private int getRadiusExitDuration() { final float radius = MathUtils.lerp(0, mTargetRadius, mTweenRadius); final float remaining = mTargetRadius - radius; return (int) (1000 * Math.sqrt(remaining / (WAVE_TOUCH_UP_ACCELERATION final float remainingRadius = mTargetRadius - getCurrentRadius(); return (int) (1000 * Math.sqrt(remainingRadius / (WAVE_TOUCH_UP_ACCELERATION + WAVE_TOUCH_DOWN_ACCELERATION) * mDensity) + 0.5); } private float getCurrentRadius() { return MathUtils.lerp(0, mTargetRadius, mTweenRadius); } private int getOpacityExitDuration() { return (int) (1000 * mOpacity / WAVE_OPACITY_DECAY_VELOCITY + 0.5f); } /** * Compute target values that are dependent on bounding. */ private void computeBoundedTargetValues() { mTargetX = (mClampedStartingX - mBounds.exactCenterX()) * .7f; mTargetY = (mClampedStartingY - mBounds.exactCenterY()) * .7f; mTargetRadius = mBoundedRadius; } @Override protected Animator createSoftwareExit() { final int radiusDuration = getRadiusExitDuration(); final int opacityDuration = getOpacityExitDuration(); final int radiusDuration; final int originDuration; final int opacityDuration; if (mIsBounded) { computeBoundedTargetValues(); radiusDuration = BOUNDED_RADIUS_EXIT_DURATION; originDuration = BOUNDED_ORIGIN_EXIT_DURATION; opacityDuration = BOUNDED_OPACITY_EXIT_DURATION; } else { radiusDuration = getRadiusExitDuration(); originDuration = radiusDuration; opacityDuration = getOpacityExitDuration(); } final ObjectAnimator tweenAll = ObjectAnimator.ofFloat(this, TWEEN_ALL, 1); tweenAll.setAutoCancel(true); tweenAll.setDuration(radiusDuration); tweenAll.setInterpolator(DECELERATE_INTERPOLATOR); final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); tweenRadius.setAutoCancel(true); tweenRadius.setDuration(radiusDuration); tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); tweenOrigin.setAutoCancel(true); tweenOrigin.setDuration(originDuration); tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR); final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, OPACITY, 0); opacity.setAutoCancel(true); Loading @@ -193,7 +257,7 @@ class RippleForeground extends RippleComponent { opacity.setInterpolator(LINEAR_INTERPOLATOR); final AnimatorSet set = new AnimatorSet(); set.play(tweenAll).with(opacity); set.play(tweenOrigin).with(tweenRadius).with(opacity); set.addListener(mAnimationListener); return set; Loading @@ -201,15 +265,25 @@ class RippleForeground extends RippleComponent { @Override protected RenderNodeAnimatorSet createHardwareExit(Paint p) { final int radiusDuration = getRadiusExitDuration(); final int opacityDuration = getOpacityExitDuration(); final int radiusDuration; final int originDuration; final int opacityDuration; if (mIsBounded) { computeBoundedTargetValues(); radiusDuration = BOUNDED_RADIUS_EXIT_DURATION; originDuration = BOUNDED_ORIGIN_EXIT_DURATION; opacityDuration = BOUNDED_OPACITY_EXIT_DURATION; } else { radiusDuration = getRadiusExitDuration(); originDuration = radiusDuration; opacityDuration = getOpacityExitDuration(); } final float startX = MathUtils.lerp( mClampedStartingX - mBounds.exactCenterX(), mOuterX, mTweenX); final float startY = MathUtils.lerp( mClampedStartingY - mBounds.exactCenterY(), mOuterY, mTweenY); final float startX = getCurrentX(); final float startY = getCurrentY(); final float startRadius = getCurrentRadius(); final float startRadius = MathUtils.lerp(0, mTargetRadius, mTweenRadius); p.setAlpha((int) (p.getAlpha() * mOpacity + 0.5f)); mPropPaint = CanvasProperty.createPaint(p); Loading @@ -221,12 +295,12 @@ class RippleForeground extends RippleComponent { radius.setDuration(radiusDuration); radius.setInterpolator(DECELERATE_INTERPOLATOR); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mOuterX); x.setDuration(radiusDuration); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX); x.setDuration(originDuration); x.setInterpolator(DECELERATE_INTERPOLATOR); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mOuterY); y.setDuration(radiusDuration); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY); y.setDuration(originDuration); y.setInterpolator(DECELERATE_INTERPOLATOR); final RenderNodeAnimator opacity = new RenderNodeAnimator(mPropPaint, Loading Loading @@ -307,14 +381,29 @@ class RippleForeground extends RippleComponent { } /** * Property for animating radius, center X, and center Y between their * initial and target values. * Property for animating radius between its initial and target values. */ private static final FloatProperty<RippleForeground> TWEEN_ALL = new FloatProperty<RippleForeground>("tweenAll") { private static final FloatProperty<RippleForeground> TWEEN_RADIUS = new FloatProperty<RippleForeground>("tweenRadius") { @Override public void setValue(RippleForeground object, float value) { object.mTweenRadius = value; object.invalidateSelf(); } @Override public Float get(RippleForeground object) { return object.mTweenRadius; } }; /** * Property for animating origin between its initial and target values. */ private static final FloatProperty<RippleForeground> TWEEN_ORIGIN = new FloatProperty<RippleForeground>("tweenOrigin") { @Override public void setValue(RippleForeground object, float value) { object.mTweenX = value; object.mTweenY = value; object.invalidateSelf(); Loading @@ -322,7 +411,7 @@ class RippleForeground extends RippleComponent { @Override public Float get(RippleForeground object) { return object.mTweenRadius; return object.mTweenX; } }; Loading