Loading graphics/java/android/graphics/drawable/RippleComponent.java +2 −6 Original line number Diff line number Diff line Loading @@ -93,12 +93,8 @@ abstract class RippleComponent { protected final void onHotspotBoundsChanged() { if (!mHasMaxRadius) { final float halfWidth = mBounds.width() / 2.0f; final float halfHeight = mBounds.height() / 2.0f; final float targetRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); onTargetRadiusChanged(targetRadius); mTargetRadius = getTargetRadius(mBounds); onTargetRadiusChanged(mTargetRadius); } } Loading graphics/java/android/graphics/drawable/RippleDrawable.java +7 −2 Original line number Diff line number Diff line Loading @@ -299,6 +299,12 @@ public class RippleDrawable extends LayerDrawable { onHotspotBoundsChanged(); } final int count = mExitingRipplesCount; final RippleForeground[] ripples = mExitingRipples; for (int i = 0; i < count; i++) { ripples[i].onBoundsChange(); } if (mBackground != null) { mBackground.onBoundsChange(); } Loading Loading @@ -560,8 +566,7 @@ public class RippleDrawable extends LayerDrawable { y = mHotspotBounds.exactCenterY(); } final boolean isBounded = isBounded(); mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded, mForceSoftware); mRipple = new RippleForeground(this, mHotspotBounds, x, y, mForceSoftware); } mRipple.setup(mState.mMaxRadius, mDensity); Loading graphics/java/android/graphics/drawable/RippleForeground.java +32 −64 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.view.DisplayListCanvas; import android.view.RenderNodeAnimator; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.PathInterpolator; import java.util.ArrayList; Loading @@ -38,18 +39,14 @@ import java.util.ArrayList; */ class RippleForeground extends RippleComponent { private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); private static final TimeInterpolator DECELERATE_INTERPOLATOR = new LogDecelerateInterpolator( 400f, 1.4f, 0); // Matches R.interpolator.fast_out_slow_in but as we have no context we can't just import that private static final TimeInterpolator DECELERATE_INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f); // Pixel-based accelerations and velocities. private static final float WAVE_TOUCH_DOWN_ACCELERATION = 2048; 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; // Time it takes for the ripple to expand private static final int RIPPLE_ENTER_DURATION = 225; // Time it takes for the ripple to slide from the touch to the center point private static final int RIPPLE_ORIGIN_DURATION = 225; private static final int OPACITY_ENTER_DURATION = 75; private static final int OPACITY_EXIT_DURATION = 150; Loading @@ -71,9 +68,6 @@ class RippleForeground extends RippleComponent { 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 = 0; Loading Loading @@ -107,19 +101,13 @@ class RippleForeground extends RippleComponent { private float mStartRadius = 0; public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY, boolean isBounded, boolean forceSoftware) { boolean forceSoftware) { super(owner, bounds); mForceSoftware = forceSoftware; mStartingX = startingX; mStartingY = startingY; if (isBounded) { mBoundedRadius = MAX_BOUNDED_RADIUS * 0.9f + (float) (MAX_BOUNDED_RADIUS * Math.random() * 0.1); } else { mBoundedRadius = 0; } // Take 60% of the maximum of the width and height, then divided half to get the radius. mStartRadius = Math.max(bounds.width(), bounds.height()) * 0.3f; } Loading @@ -127,6 +115,7 @@ class RippleForeground extends RippleComponent { @Override protected void onTargetRadiusChanged(float targetRadius) { clampStartingPosition(); switchToUiThreadAnimation(); } private void drawSoftware(Canvas c, Paint p) { Loading Loading @@ -228,16 +217,14 @@ class RippleForeground extends RippleComponent { } mRunningSwAnimators.clear(); final int duration = getRadiusDuration(); final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); tweenRadius.setDuration(duration); tweenRadius.setDuration(RIPPLE_ENTER_DURATION); tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR); tweenRadius.start(); mRunningSwAnimators.add(tweenRadius); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); tweenOrigin.setDuration(duration); tweenOrigin.setDuration(RIPPLE_ORIGIN_DURATION); tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR); tweenOrigin.start(); mRunningSwAnimators.add(tweenOrigin); Loading Loading @@ -267,20 +254,18 @@ class RippleForeground extends RippleComponent { final Paint paint = mOwner.getRipplePaint(); mPropPaint = CanvasProperty.createPaint(paint); final int radiusDuration = getRadiusDuration(); final RenderNodeAnimator radius = new RenderNodeAnimator(mPropRadius, mTargetRadius); radius.setDuration(radiusDuration); radius.setDuration(RIPPLE_ORIGIN_DURATION); radius.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(radius); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX); x.setDuration(radiusDuration); x.setDuration(RIPPLE_ORIGIN_DURATION); x.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(x); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY); y.setDuration(radiusDuration); y.setDuration(RIPPLE_ORIGIN_DURATION); y.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(y); Loading Loading @@ -333,12 +318,6 @@ class RippleForeground extends RippleComponent { return MathUtils.lerp(mClampedStartingY - mBounds.exactCenterY(), mTargetY, mTweenY); } private int getRadiusDuration() { final float remainingRadius = mTargetRadius - getCurrentRadius(); return (int) (1000 * Math.sqrt(remainingRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensityScale) + 0.5); } private float getCurrentRadius() { return MathUtils.lerp(mStartRadius, mTargetRadius, mTweenRadius); } Loading Loading @@ -402,6 +381,14 @@ class RippleForeground extends RippleComponent { } } private void clearHwProps() { mPropPaint = null; mPropRadius = null; mPropX = null; mPropY = null; mUsingProperties = false; } private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { Loading @@ -410,39 +397,20 @@ class RippleForeground extends RippleComponent { pruneSwFinished(); if (mRunningHwAnimators.isEmpty()) { mPropPaint = null; mPropRadius = null; mPropX = null; mPropY = null; clearHwProps(); } } }; /** * Interpolator with a smooth log deceleration. */ private static final class LogDecelerateInterpolator implements TimeInterpolator { private final float mBase; private final float mDrift; private final float mTimeScale; private final float mOutputScale; public LogDecelerateInterpolator(float base, float timeScale, float drift) { mBase = base; mDrift = drift; mTimeScale = 1f / timeScale; mOutputScale = 1f / computeLog(1f); } private float computeLog(float t) { return 1f - (float) Math.pow(mBase, -t * mTimeScale) + (mDrift * t); } @Override public float getInterpolation(float t) { return computeLog(t) * mOutputScale; private void switchToUiThreadAnimation() { for (int i = 0; i < mRunningHwAnimators.size(); i++) { Animator animator = mRunningHwAnimators.get(i); animator.removeListener(mAnimationListener); animator.end(); } mRunningHwAnimators.clear(); clearHwProps(); invalidateSelf(); } /** Loading Loading
graphics/java/android/graphics/drawable/RippleComponent.java +2 −6 Original line number Diff line number Diff line Loading @@ -93,12 +93,8 @@ abstract class RippleComponent { protected final void onHotspotBoundsChanged() { if (!mHasMaxRadius) { final float halfWidth = mBounds.width() / 2.0f; final float halfHeight = mBounds.height() / 2.0f; final float targetRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight); onTargetRadiusChanged(targetRadius); mTargetRadius = getTargetRadius(mBounds); onTargetRadiusChanged(mTargetRadius); } } Loading
graphics/java/android/graphics/drawable/RippleDrawable.java +7 −2 Original line number Diff line number Diff line Loading @@ -299,6 +299,12 @@ public class RippleDrawable extends LayerDrawable { onHotspotBoundsChanged(); } final int count = mExitingRipplesCount; final RippleForeground[] ripples = mExitingRipples; for (int i = 0; i < count; i++) { ripples[i].onBoundsChange(); } if (mBackground != null) { mBackground.onBoundsChange(); } Loading Loading @@ -560,8 +566,7 @@ public class RippleDrawable extends LayerDrawable { y = mHotspotBounds.exactCenterY(); } final boolean isBounded = isBounded(); mRipple = new RippleForeground(this, mHotspotBounds, x, y, isBounded, mForceSoftware); mRipple = new RippleForeground(this, mHotspotBounds, x, y, mForceSoftware); } mRipple.setup(mState.mMaxRadius, mDensity); Loading
graphics/java/android/graphics/drawable/RippleForeground.java +32 −64 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.view.DisplayListCanvas; import android.view.RenderNodeAnimator; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.PathInterpolator; import java.util.ArrayList; Loading @@ -38,18 +39,14 @@ import java.util.ArrayList; */ class RippleForeground extends RippleComponent { private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); private static final TimeInterpolator DECELERATE_INTERPOLATOR = new LogDecelerateInterpolator( 400f, 1.4f, 0); // Matches R.interpolator.fast_out_slow_in but as we have no context we can't just import that private static final TimeInterpolator DECELERATE_INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f); // Pixel-based accelerations and velocities. private static final float WAVE_TOUCH_DOWN_ACCELERATION = 2048; 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; // Time it takes for the ripple to expand private static final int RIPPLE_ENTER_DURATION = 225; // Time it takes for the ripple to slide from the touch to the center point private static final int RIPPLE_ORIGIN_DURATION = 225; private static final int OPACITY_ENTER_DURATION = 75; private static final int OPACITY_EXIT_DURATION = 150; Loading @@ -71,9 +68,6 @@ class RippleForeground extends RippleComponent { 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 = 0; Loading Loading @@ -107,19 +101,13 @@ class RippleForeground extends RippleComponent { private float mStartRadius = 0; public RippleForeground(RippleDrawable owner, Rect bounds, float startingX, float startingY, boolean isBounded, boolean forceSoftware) { boolean forceSoftware) { super(owner, bounds); mForceSoftware = forceSoftware; mStartingX = startingX; mStartingY = startingY; if (isBounded) { mBoundedRadius = MAX_BOUNDED_RADIUS * 0.9f + (float) (MAX_BOUNDED_RADIUS * Math.random() * 0.1); } else { mBoundedRadius = 0; } // Take 60% of the maximum of the width and height, then divided half to get the radius. mStartRadius = Math.max(bounds.width(), bounds.height()) * 0.3f; } Loading @@ -127,6 +115,7 @@ class RippleForeground extends RippleComponent { @Override protected void onTargetRadiusChanged(float targetRadius) { clampStartingPosition(); switchToUiThreadAnimation(); } private void drawSoftware(Canvas c, Paint p) { Loading Loading @@ -228,16 +217,14 @@ class RippleForeground extends RippleComponent { } mRunningSwAnimators.clear(); final int duration = getRadiusDuration(); final ObjectAnimator tweenRadius = ObjectAnimator.ofFloat(this, TWEEN_RADIUS, 1); tweenRadius.setDuration(duration); tweenRadius.setDuration(RIPPLE_ENTER_DURATION); tweenRadius.setInterpolator(DECELERATE_INTERPOLATOR); tweenRadius.start(); mRunningSwAnimators.add(tweenRadius); final ObjectAnimator tweenOrigin = ObjectAnimator.ofFloat(this, TWEEN_ORIGIN, 1); tweenOrigin.setDuration(duration); tweenOrigin.setDuration(RIPPLE_ORIGIN_DURATION); tweenOrigin.setInterpolator(DECELERATE_INTERPOLATOR); tweenOrigin.start(); mRunningSwAnimators.add(tweenOrigin); Loading Loading @@ -267,20 +254,18 @@ class RippleForeground extends RippleComponent { final Paint paint = mOwner.getRipplePaint(); mPropPaint = CanvasProperty.createPaint(paint); final int radiusDuration = getRadiusDuration(); final RenderNodeAnimator radius = new RenderNodeAnimator(mPropRadius, mTargetRadius); radius.setDuration(radiusDuration); radius.setDuration(RIPPLE_ORIGIN_DURATION); radius.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(radius); final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mTargetX); x.setDuration(radiusDuration); x.setDuration(RIPPLE_ORIGIN_DURATION); x.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(x); final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mTargetY); y.setDuration(radiusDuration); y.setDuration(RIPPLE_ORIGIN_DURATION); y.setInterpolator(DECELERATE_INTERPOLATOR); mPendingHwAnimators.add(y); Loading Loading @@ -333,12 +318,6 @@ class RippleForeground extends RippleComponent { return MathUtils.lerp(mClampedStartingY - mBounds.exactCenterY(), mTargetY, mTweenY); } private int getRadiusDuration() { final float remainingRadius = mTargetRadius - getCurrentRadius(); return (int) (1000 * Math.sqrt(remainingRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensityScale) + 0.5); } private float getCurrentRadius() { return MathUtils.lerp(mStartRadius, mTargetRadius, mTweenRadius); } Loading Loading @@ -402,6 +381,14 @@ class RippleForeground extends RippleComponent { } } private void clearHwProps() { mPropPaint = null; mPropRadius = null; mPropX = null; mPropY = null; mUsingProperties = false; } private final AnimatorListenerAdapter mAnimationListener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animator) { Loading @@ -410,39 +397,20 @@ class RippleForeground extends RippleComponent { pruneSwFinished(); if (mRunningHwAnimators.isEmpty()) { mPropPaint = null; mPropRadius = null; mPropX = null; mPropY = null; clearHwProps(); } } }; /** * Interpolator with a smooth log deceleration. */ private static final class LogDecelerateInterpolator implements TimeInterpolator { private final float mBase; private final float mDrift; private final float mTimeScale; private final float mOutputScale; public LogDecelerateInterpolator(float base, float timeScale, float drift) { mBase = base; mDrift = drift; mTimeScale = 1f / timeScale; mOutputScale = 1f / computeLog(1f); } private float computeLog(float t) { return 1f - (float) Math.pow(mBase, -t * mTimeScale) + (mDrift * t); } @Override public float getInterpolation(float t) { return computeLog(t) * mOutputScale; private void switchToUiThreadAnimation() { for (int i = 0; i < mRunningHwAnimators.size(); i++) { Animator animator = mRunningHwAnimators.get(i); animator.removeListener(mAnimationListener); animator.end(); } mRunningHwAnimators.clear(); clearHwProps(); invalidateSelf(); } /** Loading