diff options
| author | 2014-08-30 00:19:50 +0000 | |
|---|---|---|
| committer | 2014-08-30 00:19:51 +0000 | |
| commit | be50bd76a993b8575828df2fafab4bc5ec9de99b (patch) | |
| tree | ab09eed89a318c3ffec3fcaf3ca449aca8ae9f31 /graphics/java | |
| parent | af0fe973b3ad9b54702abcfed46ce12d4801780e (diff) | |
| parent | fdbb98e56d4668c7bfa8de59c3c438c0cb69a535 (diff) | |
Merge "Fix disappearing ripple background, treat active ripple separately" into lmp-dev
Diffstat (limited to 'graphics/java')
3 files changed, 115 insertions, 85 deletions
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java index 063ac098773e..cd919a627f35 100644 --- a/graphics/java/android/graphics/drawable/Ripple.java +++ b/graphics/java/android/graphics/drawable/Ripple.java @@ -105,6 +105,9 @@ class Ripple { /** Whether we have an explicit maximum radius. */ private boolean mHasMaxRadius; + /** Whether we were canceled externally and should avoid self-removal. */ + private boolean mCanceled; + /** * Creates a new ripple. */ @@ -295,6 +298,8 @@ class Ripple { * Starts the enter animation. */ public void enter() { + cancel(); + final int radiusDuration = (int) (1000 * Math.sqrt(mOuterRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5); @@ -332,7 +337,8 @@ class Ripple { * Starts the exit animation. */ public void exit() { - cancelSoftwareAnimations(); + cancel(); + final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius); final float remaining; if (mAnimRadius != null && mAnimRadius.isRunning()) { @@ -399,9 +405,15 @@ class Ripple { invalidateSelf(); } + /** + * Jump all animations to their end state. The caller is responsible for + * removing the ripple from the list of animating ripples. + */ public void jump() { + mCanceled = true; endSoftwareAnimations(); endHardwareAnimations(); + mCanceled = false; } private void endSoftwareAnimations() { @@ -436,6 +448,8 @@ class Ripple { mPendingAnimations.clear(); removeSelf(); } + + mHardwareAnimating = false; } private Paint getTempPaint() { @@ -479,11 +493,14 @@ class Ripple { } /** - * Cancel all animations. + * Cancels all animations. The caller is responsible for removing + * the ripple from the list of animating ripples. */ public void cancel() { + mCanceled = true; cancelSoftwareAnimations(); cancelHardwareAnimations(true); + mCanceled = false; } private void cancelSoftwareAnimations() { @@ -517,13 +534,16 @@ class Ripple { if (cancelPending && !mPendingAnimations.isEmpty()) { mPendingAnimations.clear(); - removeSelf(); } + + mHardwareAnimating = false; } private void removeSelf() { // The owner will invalidate itself. - mOwner.removeRipple(this); + if (!mCanceled) { + mOwner.removeRipple(this); + } } private void invalidateSelf() { diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java index 34e6a20e9f33..40a5e18ce6a0 100644 --- a/graphics/java/android/graphics/drawable/RippleBackground.java +++ b/graphics/java/android/graphics/drawable/RippleBackground.java @@ -107,6 +107,9 @@ class RippleBackground { /** Whether we have an explicit maximum radius. */ private boolean mHasMaxRadius; + /** Whether we were canceled externally and should avoid self-removal. */ + private boolean mCanceled; + /** * Creates a new ripple. */ @@ -284,6 +287,8 @@ class RippleBackground { * Starts the enter animation. */ public void enter() { + cancel(); + final int radiusDuration = (int) (1000 * Math.sqrt(mOuterRadius / WAVE_TOUCH_DOWN_ACCELERATION * mDensity) + 0.5); final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_ENTER_VELOCITY); @@ -321,7 +326,7 @@ class RippleBackground { * Starts the exit animation. */ public void exit() { - cancelSoftwareAnimations(); + cancel(); // Scale the outer max opacity and opacity velocity based // on the size of the outer radius. @@ -404,9 +409,15 @@ class RippleBackground { invalidateSelf(); } + /** + * Jump all animations to their end state. The caller is responsible for + * removing the ripple from the list of animating ripples. + */ public void jump() { + mCanceled = true; endSoftwareAnimations(); endHardwareAnimations(); + mCanceled = false; } private void endSoftwareAnimations() { @@ -437,6 +448,8 @@ class RippleBackground { mPendingAnimations.clear(); removeSelf(); } + + mHardwareAnimating = false; } private Paint getTempPaint() { @@ -509,11 +522,14 @@ class RippleBackground { } /** - * Cancel all animations. + * Cancel all animations. The caller is responsible for removing + * the ripple from the list of animating ripples. */ public void cancel() { + mCanceled = true; cancelSoftwareAnimations(); cancelHardwareAnimations(true); + mCanceled = false; } private void cancelSoftwareAnimations() { @@ -544,13 +560,16 @@ class RippleBackground { if (cancelPending && !mPendingAnimations.isEmpty()) { mPendingAnimations.clear(); - removeSelf(); } + + mHardwareAnimating = false; } private void removeSelf() { // The owner will invalidate itself. - mOwner.removeBackground(this); + if (!mCanceled) { + mOwner.removeBackground(this); + } } private void invalidateSelf() { diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index 7402bdb46a68..b90fd819f572 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -140,8 +140,8 @@ public class RippleDrawable extends LayerDrawable { * Lazily-created array of actively animating ripples. Inactive ripples are * pruned during draw(). The locations of these will not change. */ - private Ripple[] mAnimatingRipples; - private int mAnimatingRipplesCount = 0; + private Ripple[] mExitingRipples; + private int mExitingRipplesCount = 0; /** Paint used to control appearance of ripples. */ private Paint mRipplePaint; @@ -156,12 +156,6 @@ public class RippleDrawable extends LayerDrawable { private boolean mOverrideBounds; /** - * Whether hotspots are being cleared. Used to prevent re-entry by - * animation finish listeners. - */ - private boolean mClearingHotspots; - - /** * Constructor used for drawable inflation. */ RippleDrawable() { @@ -209,19 +203,21 @@ public class RippleDrawable extends LayerDrawable { mBackground.jump(); } - mClearingHotspots = true; - final int count = mAnimatingRipplesCount; - final Ripple[] ripples = mAnimatingRipples; + cancelExitingRipples(); + invalidateSelf(); + } + + private void cancelExitingRipples() { + final int count = mExitingRipplesCount; + final Ripple[] ripples = mExitingRipples; for (int i = 0; i < count; i++) { - ripples[i].jump(); + ripples[i].cancel(); } + if (ripples != null) { Arrays.fill(ripples, 0, count, null); } - mAnimatingRipplesCount = 0; - mClearingHotspots = false; - - invalidateSelf(); + mExitingRipplesCount = 0; } @Override @@ -287,9 +283,9 @@ public class RippleDrawable extends LayerDrawable { if (mRippleActive != active) { mRippleActive = active; if (active) { - activateRipple(); + tryRippleEnter(); } else { - removeRipple(); + tryRippleExit(); } } } @@ -298,9 +294,9 @@ public class RippleDrawable extends LayerDrawable { if (mBackgroundActive != active) { mBackgroundActive = active; if (active) { - activateBackground(); + tryBackgroundEnter(); } else { - removeBackground(); + tryBackgroundExit(); } } } @@ -327,11 +323,11 @@ public class RippleDrawable extends LayerDrawable { // If we just became visible, ensure the background and ripple // visibilities are consistent with their internal states. if (mRippleActive) { - activateRipple(); + tryRippleEnter(); } if (mBackgroundActive) { - activateBackground(); + tryBackgroundEnter(); } } @@ -491,7 +487,7 @@ public class RippleDrawable extends LayerDrawable { /** * Creates an active hotspot at the specified location. */ - private void activateBackground() { + private void tryBackgroundEnter() { if (mBackground == null) { final float x; final float y; @@ -511,7 +507,7 @@ public class RippleDrawable extends LayerDrawable { mBackground.enter(); } - private void removeBackground() { + private void tryBackgroundExit() { if (mBackground != null) { // Don't null out the background, we need it to draw! mBackground.exit(); @@ -519,10 +515,11 @@ public class RippleDrawable extends LayerDrawable { } /** - * Creates an active hotspot at the specified location. + * Attempts to start an enter animation for the active hotspot. Fails if + * there are too many animating ripples. */ - private void activateRipple() { - if (mAnimatingRipplesCount >= MAX_RIPPLES) { + private void tryRippleEnter() { + if (mExitingRipplesCount >= MAX_RIPPLES) { // This should never happen unless the user is tapping like a maniac // or there is a bug that's preventing ripples from being removed. return; @@ -545,29 +542,27 @@ public class RippleDrawable extends LayerDrawable { final int color = mState.mColor.getColorForState(getState(), Color.TRANSPARENT); mRipple.setup(mState.mMaxRadius, color, mDensity); mRipple.enter(); - - if (mAnimatingRipples == null) { - mAnimatingRipples = new Ripple[MAX_RIPPLES]; - } - mAnimatingRipples[mAnimatingRipplesCount++] = mRipple; } - @Override - public void invalidateSelf() { - // Don't invalidate when we're clearing hotspots. We'll handle that - // manually when we're done. - if (!mClearingHotspots) { - super.invalidateSelf(); - } - } - - private void removeRipple() { + /** + * Attempts to start an exit animation for the active hotspot. Fails if + * there is no active hotspot. + */ + private void tryRippleExit() { if (mRipple != null) { + if (mExitingRipples == null) { + mExitingRipples = new Ripple[MAX_RIPPLES]; + } + mExitingRipples[mExitingRipplesCount++] = mRipple; mRipple.exit(); mRipple = null; } } + /** + * Cancels and removes the active ripple, all exiting ripples, and the + * background. Nothing will be drawn after this method is called. + */ private void clearHotspots() { if (mRipple != null) { mRipple.cancel(); @@ -579,18 +574,7 @@ public class RippleDrawable extends LayerDrawable { mBackground = null; } - mClearingHotspots = true; - final int count = mAnimatingRipplesCount; - final Ripple[] ripples = mAnimatingRipples; - for (int i = 0; i < count; i++) { - ripples[i].cancel(); - } - if (ripples != null) { - Arrays.fill(ripples, 0, count, null); - } - mAnimatingRipplesCount = 0; - mClearingHotspots = false; - + cancelExitingRipples(); invalidateSelf(); } @@ -612,8 +596,8 @@ public class RippleDrawable extends LayerDrawable { * Notifies all the animating ripples that the hotspot bounds have changed. */ private void onHotspotBoundsChanged() { - final int count = mAnimatingRipplesCount; - final Ripple[] ripples = mAnimatingRipples; + final int count = mExitingRipplesCount; + final Ripple[] ripples = mExitingRipples; for (int i = 0; i < count; i++) { ripples[i].onHotspotBoundsChanged(); } @@ -683,22 +667,21 @@ public class RippleDrawable extends LayerDrawable { } /** - * Removes a ripple from the animating ripple list. + * Removes a ripple from the exiting ripple list. * * @param ripple the ripple to remove */ void removeRipple(Ripple ripple) { - if (!mClearingHotspots) { - // Ripple ripple ripple ripple. Ripple ripple. - final Ripple[] ripples = mAnimatingRipples; - final int count = mAnimatingRipplesCount; - final int index = getRippleIndex(ripple); - if (index >= 0) { - System.arraycopy(ripples, index + 1, ripples, index, count - (index + 1)); - ripples[count - 1] = null; - mAnimatingRipplesCount--; - invalidateSelf(); - } + // Ripple ripple ripple ripple. Ripple ripple. + final Ripple[] ripples = mExitingRipples; + final int count = mExitingRipplesCount; + final int index = getRippleIndex(ripple); + if (index >= 0) { + System.arraycopy(ripples, index + 1, ripples, index, count - (index + 1)); + ripples[count - 1] = null; + mExitingRipplesCount--; + + invalidateSelf(); } } @@ -710,8 +693,8 @@ public class RippleDrawable extends LayerDrawable { } private int getRippleIndex(Ripple ripple) { - final Ripple[] ripples = mAnimatingRipples; - final int count = mAnimatingRipplesCount; + final Ripple[] ripples = mExitingRipples; + final int count = mExitingRipplesCount; for (int i = 0; i < count; i++) { if (ripples[i] == ripple) { return i; @@ -727,7 +710,7 @@ public class RippleDrawable extends LayerDrawable { // We don't need a layer if we don't expect to draw any ripples, we have // an explicit mask, or if the non-mask content is all opaque. boolean needsLayer = false; - if ((mAnimatingRipplesCount > 0 || mBackground != null) && mMask == null) { + if ((mExitingRipplesCount > 0 || mBackground != null) && mMask == null) { for (int i = 0; i < count; i++) { if (array[i].mId != R.id.mask && array[i].mDrawable.getOpacity() != PixelFormat.OPAQUE) { @@ -831,10 +814,17 @@ public class RippleDrawable extends LayerDrawable { int restoreTranslate = -1; // Draw ripples and update the animating ripples array. - final int count = mAnimatingRipplesCount; - final Ripple[] ripples = mAnimatingRipples; - for (int i = 0; i < count; i++) { - final Ripple ripple = ripples[i]; + final int count = mExitingRipplesCount; + final Ripple[] ripples = mExitingRipples; + for (int i = 0; i <= count; i++) { + final Ripple ripple; + if (i < count) { + ripple = ripples[i]; + } else if (mRipple != null) { + ripple = mRipple; + } else { + continue; + } // If we're masking the ripple layer, make sure we have a layer // first. This will merge SRC_OVER (directly) onto the canvas. @@ -898,8 +888,9 @@ public class RippleDrawable extends LayerDrawable { final int cX = (int) mHotspotBounds.exactCenterX(); final int cY = (int) mHotspotBounds.exactCenterY(); final Rect rippleBounds = mTempRect; - final Ripple[] activeRipples = mAnimatingRipples; - final int N = mAnimatingRipplesCount; + + final Ripple[] activeRipples = mExitingRipples; + final int N = mExitingRipplesCount; for (int i = 0; i < N; i++) { activeRipples[i].getBounds(rippleBounds); rippleBounds.offset(cX, cY); |