summaryrefslogtreecommitdiffstats
path: root/graphics/java/android/graphics/drawable/RippleBackground.java
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/java/android/graphics/drawable/RippleBackground.java')
-rw-r--r--graphics/java/android/graphics/drawable/RippleBackground.java148
1 files changed, 77 insertions, 71 deletions
diff --git a/graphics/java/android/graphics/drawable/RippleBackground.java b/graphics/java/android/graphics/drawable/RippleBackground.java
index faa89bf..fae4902 100644
--- a/graphics/java/android/graphics/drawable/RippleBackground.java
+++ b/graphics/java/android/graphics/drawable/RippleBackground.java
@@ -24,7 +24,6 @@ import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Color;
import android.graphics.Paint;
-import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.MathUtils;
import android.view.HardwareCanvas;
@@ -43,26 +42,23 @@ class RippleBackground {
private static final float WAVE_OPACITY_DECAY_VELOCITY = 3.0f / GLOBAL_SPEED;
private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MAX = 4.5f * GLOBAL_SPEED;
private static final float WAVE_OUTER_OPACITY_EXIT_VELOCITY_MIN = 1.5f * GLOBAL_SPEED;
- private static final float WAVE_OUTER_OPACITY_ENTER_VELOCITY = 10.0f * GLOBAL_SPEED;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MAX = 200f;
private static final float WAVE_OUTER_SIZE_INFLUENCE_MIN = 40f;
+ private static final int ENTER_DURATION = 667;
+ private static final int ENTER_DURATION_FAST = 100;
+
// Hardware animators.
private final ArrayList<RenderNodeAnimator> mRunningAnimations =
new ArrayList<RenderNodeAnimator>();
- private final ArrayList<RenderNodeAnimator> mPendingAnimations =
- new ArrayList<RenderNodeAnimator>();
private final RippleDrawable mOwner;
/** Bounds used for computing max radius. */
private final Rect mBounds;
- /** Full-opacity color for drawing this ripple. */
- private int mColorOpaque;
-
- /** Maximum alpha value for drawing this ripple. */
- private int mColorAlpha;
+ /** ARGB color for drawing this ripple. */
+ private int mColor;
/** Maximum ripple radius. */
private float mOuterRadius;
@@ -96,6 +92,11 @@ class RippleBackground {
/** Whether we have an explicit maximum radius. */
private boolean mHasMaxRadius;
+ private boolean mHasPendingHardwareExit;
+ private int mPendingOpacityDuration;
+ private int mPendingInflectionDuration;
+ private int mPendingInflectionOpacity;
+
/**
* Creates a new ripple.
*/
@@ -104,10 +105,7 @@ class RippleBackground {
mBounds = bounds;
}
- public void setup(int maxRadius, int color, float density) {
- mColorOpaque = color | 0xFF000000;
- mColorAlpha = Color.alpha(color) / 2;
-
+ public void setup(int maxRadius, float density) {
if (maxRadius != RippleDrawable.RADIUS_AUTO) {
mHasMaxRadius = true;
mOuterRadius = maxRadius;
@@ -122,10 +120,6 @@ class RippleBackground {
mDensity = density;
}
- public boolean isHardwareAnimating() {
- return mHardwareAnimating;
- }
-
public void onHotspotBoundsChanged() {
if (!mHasMaxRadius) {
final float halfWidth = mBounds.width() / 2.0f;
@@ -149,6 +143,8 @@ class RippleBackground {
* Draws the ripple centered at (0,0) using the specified paint.
*/
public boolean draw(Canvas c, Paint p) {
+ mColor = p.getColor();
+
final boolean canUseHardware = c.isHardwareAccelerated();
if (mCanUseHardware != canUseHardware && mCanUseHardware) {
// We've switched from hardware to non-hardware mode. Panic.
@@ -157,8 +153,8 @@ class RippleBackground {
mCanUseHardware = canUseHardware;
final boolean hasContent;
- if (canUseHardware && mHardwareAnimating) {
- hasContent = drawHardware((HardwareCanvas) c);
+ if (canUseHardware && (mHardwareAnimating || mHasPendingHardwareExit)) {
+ hasContent = drawHardware((HardwareCanvas) c, p);
} else {
hasContent = drawSoftware(c, p);
}
@@ -167,28 +163,13 @@ class RippleBackground {
}
public boolean shouldDraw() {
- final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
- return mCanUseHardware && mHardwareAnimating || outerAlpha > 0 && mOuterRadius > 0;
+ return (mCanUseHardware && mHardwareAnimating) || (mOuterOpacity > 0 && mOuterRadius > 0);
}
- private boolean drawHardware(HardwareCanvas c) {
- // If we have any pending hardware animations, cancel any running
- // animations and start those now.
- final ArrayList<RenderNodeAnimator> pendingAnimations = mPendingAnimations;
- final int N = pendingAnimations.size();
- if (N > 0) {
+ private boolean drawHardware(HardwareCanvas c, Paint p) {
+ if (mHasPendingHardwareExit) {
cancelHardwareAnimations(false);
-
- // We canceled old animations, but we're about to run new ones.
- mHardwareAnimating = true;
-
- for (int i = 0; i < N; i++) {
- pendingAnimations.get(i).setTarget(c);
- pendingAnimations.get(i).start();
- }
-
- mRunningAnimations.addAll(pendingAnimations);
- pendingAnimations.clear();
+ startPendingHardwareExit(c, p);
}
c.drawCircle(mPropOuterX, mPropOuterY, mPropOuterRadius, mPropOuterPaint);
@@ -199,12 +180,13 @@ class RippleBackground {
private boolean drawSoftware(Canvas c, Paint p) {
boolean hasContent = false;
- p.setColor(mColorOpaque);
- final int outerAlpha = (int) (mColorAlpha * mOuterOpacity + 0.5f);
- if (outerAlpha > 0 && mOuterRadius > 0) {
- p.setAlpha(outerAlpha);
- p.setStyle(Style.FILL);
- c.drawCircle(mOuterX, mOuterY, mOuterRadius, p);
+ final int paintAlpha = p.getAlpha();
+ final int alpha = (int) (paintAlpha * mOuterOpacity + 0.5f);
+ final float radius = mOuterRadius;
+ if (alpha > 0 && radius > 0) {
+ p.setAlpha(alpha);
+ c.drawCircle(mOuterX, mOuterY, radius, p);
+ p.setAlpha(paintAlpha);
hasContent = true;
}
@@ -224,21 +206,20 @@ class RippleBackground {
/**
* Starts the enter animation.
*/
- public void enter() {
+ public void enter(boolean fast) {
cancel();
- final int outerDuration = (int) (1000 * 1.0f / WAVE_OUTER_OPACITY_ENTER_VELOCITY);
- final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1);
- outer.setAutoCancel(true);
- outer.setDuration(outerDuration);
- outer.setInterpolator(LINEAR_INTERPOLATOR);
+ final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1);
+ opacity.setAutoCancel(true);
+ opacity.setDuration(fast ? ENTER_DURATION_FAST : ENTER_DURATION);
+ opacity.setInterpolator(LINEAR_INTERPOLATOR);
- mAnimOuterOpacity = outer;
+ mAnimOuterOpacity = opacity;
// Enter animations always run on the UI thread, since it's unlikely
// that anything interesting is happening until the user lifts their
// finger.
- outer.start();
+ opacity.start();
}
/**
@@ -261,24 +242,36 @@ class RippleBackground {
// outer(t) = mOuterOpacity + t * WAVE_OUTER_OPACITY_VELOCITY / 1000
final int inflectionDuration = Math.max(0, (int) (1000 * (1 - mOuterOpacity)
/ (WAVE_OPACITY_DECAY_VELOCITY + outerOpacityVelocity) + 0.5f));
- final int inflectionOpacity = (int) (mColorAlpha * (mOuterOpacity
+ final int inflectionOpacity = (int) (Color.alpha(mColor) * (mOuterOpacity
+ inflectionDuration * outerOpacityVelocity * outerSizeInfluence / 1000) + 0.5f);
if (mCanUseHardware) {
- exitHardware(opacityDuration, inflectionDuration, inflectionOpacity);
+ createPendingHardwareExit(opacityDuration, inflectionDuration, inflectionOpacity);
} else {
exitSoftware(opacityDuration, inflectionDuration, inflectionOpacity);
}
}
- private void exitHardware(int opacityDuration, int inflectionDuration, int inflectionOpacity) {
- mPendingAnimations.clear();
+ private void createPendingHardwareExit(
+ int opacityDuration, int inflectionDuration, int inflectionOpacity) {
+ mHasPendingHardwareExit = true;
+ mPendingOpacityDuration = opacityDuration;
+ mPendingInflectionDuration = inflectionDuration;
+ mPendingInflectionOpacity = inflectionOpacity;
+
+ // The animation will start on the next draw().
+ invalidateSelf();
+ }
+
+ private void startPendingHardwareExit(HardwareCanvas c, Paint p) {
+ mHasPendingHardwareExit = false;
+
+ final int opacityDuration = mPendingOpacityDuration;
+ final int inflectionDuration = mPendingInflectionDuration;
+ final int inflectionOpacity = mPendingInflectionOpacity;
- final Paint outerPaint = getTempPaint();
- outerPaint.setAntiAlias(true);
- outerPaint.setColor(mColorOpaque);
- outerPaint.setAlpha((int) (mColorAlpha * mOuterOpacity + 0.5f));
- outerPaint.setStyle(Style.FILL);
+ final Paint outerPaint = getTempPaint(p);
+ outerPaint.setAlpha((int) (outerPaint.getAlpha() * mOuterOpacity + 0.5f));
mPropOuterPaint = CanvasProperty.createPaint(outerPaint);
mPropOuterRadius = CanvasProperty.createFloat(mOuterRadius);
mPropOuterX = CanvasProperty.createFloat(mOuterX);
@@ -302,8 +295,10 @@ class RippleBackground {
outerFadeOutAnim.setStartDelay(inflectionDuration);
outerFadeOutAnim.setStartValue(inflectionOpacity);
outerFadeOutAnim.addListener(mAnimationListener);
+ outerFadeOutAnim.setTarget(c);
+ outerFadeOutAnim.start();
- mPendingAnimations.add(outerFadeOutAnim);
+ mRunningAnimations.add(outerFadeOutAnim);
} else {
outerOpacityAnim.addListener(mAnimationListener);
}
@@ -315,14 +310,15 @@ class RippleBackground {
outerOpacityAnim.addListener(mAnimationListener);
}
- mPendingAnimations.add(outerOpacityAnim);
+ outerOpacityAnim.setTarget(c);
+ outerOpacityAnim.start();
+
+ mRunningAnimations.add(outerOpacityAnim);
mHardwareAnimating = true;
// Set up the software values to match the hardware end values.
mOuterOpacity = 0;
-
- invalidateSelf();
}
/**
@@ -341,10 +337,11 @@ class RippleBackground {
}
}
- private Paint getTempPaint() {
+ private Paint getTempPaint(Paint original) {
if (mTempPaint == null) {
mTempPaint = new Paint();
}
+ mTempPaint.set(original);
return mTempPaint;
}
@@ -402,7 +399,7 @@ class RippleBackground {
*/
public void cancel() {
cancelSoftwareAnimations();
- cancelHardwareAnimations(true);
+ cancelHardwareAnimations(false);
}
private void cancelSoftwareAnimations() {
@@ -415,16 +412,25 @@ class RippleBackground {
/**
* Cancels any running hardware animations.
*/
- private void cancelHardwareAnimations(boolean cancelPending) {
+ private void cancelHardwareAnimations(boolean jumpToEnd) {
final ArrayList<RenderNodeAnimator> runningAnimations = mRunningAnimations;
final int N = runningAnimations.size();
for (int i = 0; i < N; i++) {
- runningAnimations.get(i).cancel();
+ if (jumpToEnd) {
+ runningAnimations.get(i).end();
+ } else {
+ runningAnimations.get(i).cancel();
+ }
}
runningAnimations.clear();
- if (cancelPending && !mPendingAnimations.isEmpty()) {
- mPendingAnimations.clear();
+ if (mHasPendingHardwareExit) {
+ // If we had a pending hardware exit, jump to the end state.
+ mHasPendingHardwareExit = false;
+
+ if (jumpToEnd) {
+ mOuterOpacity = 0;
+ }
}
mHardwareAnimating = false;