summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2014-06-01 16:48:31 -0700
committerAlan Viverette <alanv@google.com>2014-06-01 16:48:31 -0700
commitdc6046fca37264b48e9c959f38d08cfb78f436ed (patch)
tree8f4ede2a641dd21fc6ec64fb2ec6621a11b2c117 /graphics
parentc6c967b68a9c29e0930bcfa32548633596fe5745 (diff)
downloadframeworks_base-dc6046fca37264b48e9c959f38d08cfb78f436ed.zip
frameworks_base-dc6046fca37264b48e9c959f38d08cfb78f436ed.tar.gz
frameworks_base-dc6046fca37264b48e9c959f38d08cfb78f436ed.tar.bz2
Allow ripple bounds to change during enter animation
BUG: 15315168 Change-Id: I7588be96648318473998cfd5deba678224f1db51
Diffstat (limited to 'graphics')
-rw-r--r--graphics/java/android/graphics/drawable/Ripple.java255
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java14
2 files changed, 135 insertions, 134 deletions
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 65b6814..ada741b 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -85,15 +85,13 @@ class Ripple {
// Software rendering properties.
private float mOuterOpacity = 0;
private float mOpacity = 1;
- private float mRadius = 0;
private float mOuterX;
private float mOuterY;
- private float mX;
- private float mY;
// Values used to tween between the start and end positions.
- private float mXGravity = 0;
- private float mYGravity = 0;
+ private float mTweenRadius = 0;
+ private float mTweenX = 0;
+ private float mTweenY = 0;
/** Whether we should be drawing hardware animations. */
private boolean mHardwareAnimating;
@@ -101,6 +99,9 @@ class Ripple {
/** Whether we can use hardware acceleration for the exit animation. */
private boolean mCanUseHardware;
+ /** Whether we have an explicit maximum radius. */
+ private boolean mHasMaxRadius;
+
/**
* Creates a new ripple.
*/
@@ -115,6 +116,7 @@ class Ripple {
mColor = color | 0xFF000000;
if (maxRadius != RippleDrawable.RADIUS_AUTO) {
+ mHasMaxRadius = true;
mOuterRadius = maxRadius;
} else {
final float halfWidth = mBounds.width() / 2.0f;
@@ -127,13 +129,12 @@ class Ripple {
mDensity = density;
}
- public void setRadius(float r) {
- mRadius = r;
- invalidateSelf();
- }
-
- public float getRadius() {
- return mRadius;
+ public void onHotspotBoundsChanged() {
+ if (!mHasMaxRadius) {
+ final float halfWidth = mBounds.width() / 2.0f;
+ final float halfHeight = mBounds.height() / 2.0f;
+ mOuterRadius = (float) Math.sqrt(halfWidth * halfWidth + halfHeight * halfHeight);
+ }
}
public void setOpacity(float a) {
@@ -154,40 +155,31 @@ class Ripple {
return mOuterOpacity;
}
- public void setXGravity(float x) {
- mXGravity = x;
- invalidateSelf();
- }
-
- public float getXGravity() {
- return mXGravity;
- }
-
- public void setYGravity(float y) {
- mYGravity = y;
+ public void setRadiusGravity(float r) {
+ mTweenRadius = r;
invalidateSelf();
}
- public float getYGravity() {
- return mYGravity;
+ public float getRadiusGravity() {
+ return mTweenRadius;
}
- public void setX(float x) {
- mX = x;
+ public void setXGravity(float x) {
+ mTweenX = x;
invalidateSelf();
}
- public float getX() {
- return mX;
+ public float getXGravity() {
+ return mTweenX;
}
- public void setY(float y) {
- mY = y;
+ public void setYGravity(float y) {
+ mTweenY = y;
invalidateSelf();
}
- public float getY() {
- return mY;
+ public float getYGravity() {
+ return mTweenY;
}
/**
@@ -249,12 +241,13 @@ class Ripple {
}
final int alpha = (int) (255 * mOpacity + 0.5f);
- if (alpha > 0 && mRadius > 0) {
- final float x = MathUtils.lerp(mStartingX - mBounds.exactCenterX(), mOuterX, mXGravity);
- final float y = MathUtils.lerp(mStartingY - mBounds.exactCenterY(), mOuterY, mYGravity);
+ final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
+ if (alpha > 0 && radius > 0) {
+ final float x = MathUtils.lerp(mStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
+ final float y = MathUtils.lerp(mStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
p.setAlpha(alpha);
p.setStyle(Style.FILL);
- c.drawCircle(x, y, mRadius, p);
+ c.drawCircle(x, y, radius, p);
hasContent = true;
}
@@ -264,17 +257,13 @@ class Ripple {
}
/**
- * Returns the maximum bounds for this ripple.
+ * 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 r = (int) mOuterRadius;
bounds.set(outerX - r, outerY - r, outerX + r, outerY + r);
-
- final int x = (int) mX;
- final int y = (int) mY;
- bounds.union(x - r, y - r, x + r, y + r);
}
/**
@@ -290,14 +279,11 @@ class Ripple {
* Starts the enter animation.
*/
public void enter() {
- mX = mStartingX - mBounds.exactCenterX();
- mY = mStartingY - mBounds.exactCenterY();
-
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_VELOCITY);
- final ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radius", 0, mOuterRadius);
+ final ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radiusGravity", 1);
radius.setAutoCancel(true);
radius.setDuration(radiusDuration);
radius.setInterpolator(LINEAR_INTERPOLATOR);
@@ -335,12 +321,10 @@ class Ripple {
public void exit() {
cancelSoftwareAnimations();
- mX = MathUtils.lerp(mStartingX - mBounds.exactCenterX(), mOuterX, mXGravity);
- mY = MathUtils.lerp(mStartingY - mBounds.exactCenterY(), mOuterY, mYGravity);
-
+ final float radius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
final float remaining;
if (mAnimRadius != null && mAnimRadius.isRunning()) {
- remaining = mOuterRadius - mRadius;
+ remaining = mOuterRadius - radius;
} else {
remaining = mOuterRadius;
}
@@ -368,6 +352,8 @@ class Ripple {
int inflectionOpacity) {
mPendingAnimations.clear();
+ final float startX = MathUtils.lerp(mStartingX - mBounds.exactCenterX(), mOuterX, mTweenX);
+ final float startY = MathUtils.lerp(mStartingY - mBounds.exactCenterY(), mOuterY, mTweenY);
final Paint outerPaint = new Paint();
outerPaint.setAntiAlias(true);
outerPaint.setColor(mColor);
@@ -378,68 +364,69 @@ class Ripple {
mPropOuterX = CanvasProperty.createFloat(mOuterX);
mPropOuterY = CanvasProperty.createFloat(mOuterY);
+ final float startRadius = MathUtils.lerp(0, mOuterRadius, mTweenRadius);
final Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(mColor);
paint.setAlpha((int) (255 * mOpacity + 0.5f));
paint.setStyle(Style.FILL);
mPropPaint = CanvasProperty.createPaint(paint);
- mPropRadius = CanvasProperty.createFloat(mRadius);
- mPropX = CanvasProperty.createFloat(mX);
- mPropY = CanvasProperty.createFloat(mY);
+ mPropRadius = CanvasProperty.createFloat(startRadius);
+ mPropX = CanvasProperty.createFloat(startX);
+ mPropY = CanvasProperty.createFloat(startY);
- final RenderNodeAnimator radius = new RenderNodeAnimator(mPropRadius, mOuterRadius);
- radius.setDuration(radiusDuration);
- radius.setInterpolator(LINEAR_INTERPOLATOR);
+ final RenderNodeAnimator radiusAnim = new RenderNodeAnimator(mPropRadius, mOuterRadius);
+ radiusAnim.setDuration(radiusDuration);
+ radiusAnim.setInterpolator(LINEAR_INTERPOLATOR);
- final RenderNodeAnimator x = new RenderNodeAnimator(mPropX, mOuterX);
- x.setDuration(radiusDuration);
- x.setInterpolator(LINEAR_INTERPOLATOR);
+ final RenderNodeAnimator xAnim = new RenderNodeAnimator(mPropX, mOuterX);
+ xAnim.setDuration(radiusDuration);
+ xAnim.setInterpolator(LINEAR_INTERPOLATOR);
- final RenderNodeAnimator y = new RenderNodeAnimator(mPropY, mOuterY);
- y.setDuration(radiusDuration);
- y.setInterpolator(LINEAR_INTERPOLATOR);
+ final RenderNodeAnimator yAnim = new RenderNodeAnimator(mPropY, mOuterY);
+ yAnim.setDuration(radiusDuration);
+ yAnim.setInterpolator(LINEAR_INTERPOLATOR);
- final RenderNodeAnimator opacity = new RenderNodeAnimator(mPropPaint,
+ final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPropPaint,
RenderNodeAnimator.PAINT_ALPHA, 0);
- opacity.setDuration(opacityDuration);
- opacity.setInterpolator(LINEAR_INTERPOLATOR);
+ opacityAnim.setDuration(opacityDuration);
+ opacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
- final RenderNodeAnimator outerOpacity;
+ final RenderNodeAnimator outerOpacityAnim;
if (outerInflection > 0) {
// Outer opacity continues to increase for a bit.
- outerOpacity = new RenderNodeAnimator(
+ outerOpacityAnim = new RenderNodeAnimator(
mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, inflectionOpacity);
- outerOpacity.setDuration(outerInflection);
- outerOpacity.setInterpolator(LINEAR_INTERPOLATOR);
+ outerOpacityAnim.setDuration(outerInflection);
+ outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
// Chain the outer opacity exit animation.
final int outerDuration = opacityDuration - outerInflection;
if (outerDuration > 0) {
- final RenderNodeAnimator outerFadeOut = new RenderNodeAnimator(
+ final RenderNodeAnimator outerFadeOutAnim = new RenderNodeAnimator(
mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, 0);
- outerFadeOut.setDuration(outerDuration);
- outerFadeOut.setInterpolator(LINEAR_INTERPOLATOR);
- outerFadeOut.setStartDelay(outerInflection);
- outerFadeOut.addListener(mAnimationListener);
+ outerFadeOutAnim.setDuration(outerDuration);
+ outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ outerFadeOutAnim.setStartDelay(outerInflection);
+ outerFadeOutAnim.addListener(mAnimationListener);
- mPendingAnimations.add(outerFadeOut);
+ mPendingAnimations.add(outerFadeOutAnim);
} else {
- outerOpacity.addListener(mAnimationListener);
+ outerOpacityAnim.addListener(mAnimationListener);
}
} else {
- outerOpacity = new RenderNodeAnimator(
+ outerOpacityAnim = new RenderNodeAnimator(
mPropOuterPaint, RenderNodeAnimator.PAINT_ALPHA, 0);
- outerOpacity.setInterpolator(LINEAR_INTERPOLATOR);
- outerOpacity.setDuration(opacityDuration);
- outerOpacity.addListener(mAnimationListener);
+ outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ outerOpacityAnim.setDuration(opacityDuration);
+ outerOpacityAnim.addListener(mAnimationListener);
}
- mPendingAnimations.add(radius);
- mPendingAnimations.add(opacity);
- mPendingAnimations.add(outerOpacity);
- mPendingAnimations.add(x);
- mPendingAnimations.add(y);
+ mPendingAnimations.add(radiusAnim);
+ mPendingAnimations.add(opacityAnim);
+ mPendingAnimations.add(outerOpacityAnim);
+ mPendingAnimations.add(xAnim);
+ mPendingAnimations.add(yAnim);
mHardwareAnimating = true;
@@ -448,51 +435,51 @@ class Ripple {
private void exitSoftware(int radiusDuration, int opacityDuration, int outerInflection,
int inflectionOpacity) {
- final ObjectAnimator radius = ObjectAnimator.ofFloat(this, "radius", mOuterRadius);
- radius.setAutoCancel(true);
- radius.setDuration(radiusDuration);
- radius.setInterpolator(LINEAR_INTERPOLATOR);
-
- final ObjectAnimator x = ObjectAnimator.ofFloat(this, "x", mOuterX);
- x.setAutoCancel(true);
- x.setDuration(radiusDuration);
- x.setInterpolator(LINEAR_INTERPOLATOR);
-
- final ObjectAnimator y = ObjectAnimator.ofFloat(this, "y", mOuterY);
- y.setAutoCancel(true);
- y.setDuration(radiusDuration);
- y.setInterpolator(LINEAR_INTERPOLATOR);
-
- final ObjectAnimator opacity = ObjectAnimator.ofFloat(this, "opacity", 0);
- opacity.setAutoCancel(true);
- opacity.setDuration(opacityDuration);
- opacity.setInterpolator(LINEAR_INTERPOLATOR);
-
- final ObjectAnimator outerOpacity;
+ final ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this, "radiusGravity", 1);
+ radiusAnim.setAutoCancel(true);
+ radiusAnim.setDuration(radiusDuration);
+ radiusAnim.setInterpolator(LINEAR_INTERPOLATOR);
+
+ final ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity", 1);
+ xAnim.setAutoCancel(true);
+ xAnim.setDuration(radiusDuration);
+ xAnim.setInterpolator(LINEAR_INTERPOLATOR);
+
+ final ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity", 1);
+ yAnim.setAutoCancel(true);
+ yAnim.setDuration(radiusDuration);
+ yAnim.setInterpolator(LINEAR_INTERPOLATOR);
+
+ final ObjectAnimator opacityAnim = ObjectAnimator.ofFloat(this, "opacity", 0);
+ opacityAnim.setAutoCancel(true);
+ opacityAnim.setDuration(opacityDuration);
+ opacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
+
+ final ObjectAnimator outerOpacityAnim;
if (outerInflection > 0) {
// Outer opacity continues to increase for a bit.
- outerOpacity = ObjectAnimator.ofFloat(this,
+ outerOpacityAnim = ObjectAnimator.ofFloat(this,
"outerOpacity", inflectionOpacity / 255.0f);
- outerOpacity.setAutoCancel(true);
- outerOpacity.setDuration(outerInflection);
- outerOpacity.setInterpolator(LINEAR_INTERPOLATOR);
+ outerOpacityAnim.setAutoCancel(true);
+ outerOpacityAnim.setDuration(outerInflection);
+ outerOpacityAnim.setInterpolator(LINEAR_INTERPOLATOR);
// Chain the outer opacity exit animation.
final int outerDuration = opacityDuration - outerInflection;
if (outerDuration > 0) {
- outerOpacity.addListener(new AnimatorListenerAdapter() {
+ outerOpacityAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- final ObjectAnimator outerFadeOut = ObjectAnimator.ofFloat(Ripple.this,
+ final ObjectAnimator outerFadeOutAnim = ObjectAnimator.ofFloat(Ripple.this,
"outerOpacity", 0);
- outerFadeOut.setAutoCancel(true);
- outerFadeOut.setDuration(outerDuration);
- outerFadeOut.setInterpolator(LINEAR_INTERPOLATOR);
- outerFadeOut.addListener(mAnimationListener);
+ outerFadeOutAnim.setAutoCancel(true);
+ outerFadeOutAnim.setDuration(outerDuration);
+ outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ outerFadeOutAnim.addListener(mAnimationListener);
- mAnimOuterOpacity = outerFadeOut;
+ mAnimOuterOpacity = outerFadeOutAnim;
- outerFadeOut.start();
+ outerFadeOutAnim.start();
}
@Override
@@ -501,26 +488,26 @@ class Ripple {
}
});
} else {
- outerOpacity.addListener(mAnimationListener);
+ outerOpacityAnim.addListener(mAnimationListener);
}
} else {
- outerOpacity = ObjectAnimator.ofFloat(this, "outerOpacity", 0);
- outerOpacity.setAutoCancel(true);
- outerOpacity.setDuration(opacityDuration);
- outerOpacity.addListener(mAnimationListener);
+ outerOpacityAnim = ObjectAnimator.ofFloat(this, "outerOpacity", 0);
+ outerOpacityAnim.setAutoCancel(true);
+ outerOpacityAnim.setDuration(opacityDuration);
+ outerOpacityAnim.addListener(mAnimationListener);
}
- mAnimRadius = radius;
- mAnimOpacity = opacity;
- mAnimOuterOpacity = outerOpacity;
- mAnimX = opacity;
- mAnimY = opacity;
-
- radius.start();
- opacity.start();
- outerOpacity.start();
- x.start();
- y.start();
+ mAnimRadius = radiusAnim;
+ mAnimOpacity = opacityAnim;
+ mAnimOuterOpacity = outerOpacityAnim;
+ mAnimX = opacityAnim;
+ mAnimY = opacityAnim;
+
+ radiusAnim.start();
+ opacityAnim.start();
+ outerOpacityAnim.start();
+ xAnim.start();
+ yAnim.start();
}
/**
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 4e786f0..9d7a8b6 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -213,6 +213,7 @@ public class RippleDrawable extends LayerDrawable {
if (!mOverrideBounds) {
mHotspotBounds.set(bounds);
+ onHotspotBoundsChanged();
}
invalidateSelf();
@@ -452,6 +453,19 @@ public class RippleDrawable extends LayerDrawable {
public void setHotspotBounds(int left, int top, int right, int bottom) {
mOverrideBounds = true;
mHotspotBounds.set(left, top, right, bottom);
+
+ onHotspotBoundsChanged();
+ }
+
+ /**
+ * Notifies all the animating ripples that the hotspot bounds have changed.
+ */
+ private void onHotspotBoundsChanged() {
+ final int count = mAnimatingRipplesCount;
+ final Ripple[] ripples = mAnimatingRipples;
+ for (int i = 0; i < count; i++) {
+ ripples[i].onHotspotBoundsChanged();
+ }
}
@Override