Merge "Update ripple spec, fix ripple mask, rotate progress drawable" into lmp-preview-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1c121e124a
@@ -19,10 +19,8 @@
|
||||
<color name="background_quantum_dark">#ff212121</color>
|
||||
<color name="background_quantum_light">#fffafafa</color>
|
||||
|
||||
<!-- Black 27% -->
|
||||
<color name="ripple_quantum_light">#45000000</color>
|
||||
<!-- White 19% -->
|
||||
<color name="ripple_quantum_dark">#30ffffff</color>
|
||||
<color name="ripple_quantum_light">#20444444</color>
|
||||
<color name="ripple_quantum_dark">#20ffffff</color>
|
||||
|
||||
<color name="button_quantum_dark">#ff5a595b</color>
|
||||
<color name="button_quantum_light">#ffd6d7d7</color>
|
||||
|
||||
@@ -54,6 +54,12 @@ class QuantumProgressDrawable extends Drawable implements Animatable {
|
||||
private static final TimeInterpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator();
|
||||
private static final TimeInterpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator();
|
||||
|
||||
/** The duration of a single progress spin in milliseconds. */
|
||||
private static final int ANIMATION_DURATION = 1000 * 80 / 60;
|
||||
|
||||
/** The number of points in the progress "star". */
|
||||
private static final int NUM_POINTS = 5;
|
||||
|
||||
/** The list of animators operating on this drawable. */
|
||||
private final ArrayList<Animator> mAnimators = new ArrayList<Animator>();
|
||||
|
||||
@@ -62,6 +68,9 @@ class QuantumProgressDrawable extends Drawable implements Animatable {
|
||||
|
||||
private QuantumProgressState mState;
|
||||
|
||||
/** Canvas rotation in degrees. */
|
||||
private float mRotation;
|
||||
|
||||
private boolean mMutated;
|
||||
|
||||
public QuantumProgressDrawable() {
|
||||
@@ -187,7 +196,11 @@ class QuantumProgressDrawable extends Drawable implements Animatable {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas c) {
|
||||
mRing.draw(c, getBounds());
|
||||
final Rect bounds = getBounds();
|
||||
final int saveCount = c.save();
|
||||
c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY());
|
||||
mRing.draw(c, bounds);
|
||||
c.restoreToCount(saveCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -210,6 +223,15 @@ class QuantumProgressDrawable extends Drawable implements Animatable {
|
||||
return mRing.getColorFilter();
|
||||
}
|
||||
|
||||
private void setRotation(float rotation) {
|
||||
mRotation = rotation;
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
private float getRotation() {
|
||||
return mRotation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
@@ -256,26 +278,33 @@ class QuantumProgressDrawable extends Drawable implements Animatable {
|
||||
final Ring ring = mRing;
|
||||
|
||||
final ObjectAnimator endTrim = ObjectAnimator.ofFloat(ring, "endTrim", 0, 0.75f);
|
||||
endTrim.setDuration(1000 * 80 / 60);
|
||||
endTrim.setDuration(ANIMATION_DURATION);
|
||||
endTrim.setInterpolator(START_CURVE_INTERPOLATOR);
|
||||
endTrim.setRepeatCount(ObjectAnimator.INFINITE);
|
||||
endTrim.setRepeatMode(ObjectAnimator.RESTART);
|
||||
|
||||
final ObjectAnimator startTrim = ObjectAnimator.ofFloat(ring, "startTrim", 0.0f, 0.75f);
|
||||
startTrim.setDuration(1000 * 80 / 60);
|
||||
startTrim.setDuration(ANIMATION_DURATION);
|
||||
startTrim.setInterpolator(END_CURVE_INTERPOLATOR);
|
||||
startTrim.setRepeatCount(ObjectAnimator.INFINITE);
|
||||
startTrim.setRepeatMode(ObjectAnimator.RESTART);
|
||||
|
||||
final ObjectAnimator rotation = ObjectAnimator.ofFloat(ring, "rotation", 0.0f, 0.25f);
|
||||
rotation.setDuration(1000 * 80 / 60);
|
||||
rotation.setDuration(ANIMATION_DURATION);
|
||||
rotation.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
rotation.setRepeatCount(ObjectAnimator.INFINITE);
|
||||
rotation.setRepeatMode(ObjectAnimator.RESTART);
|
||||
|
||||
final ObjectAnimator groupRotation = ObjectAnimator.ofFloat(this, "rotation", 0.0f, 360.0f);
|
||||
groupRotation.setDuration(NUM_POINTS * ANIMATION_DURATION);
|
||||
groupRotation.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
groupRotation.setRepeatCount(ObjectAnimator.INFINITE);
|
||||
groupRotation.setRepeatMode(ObjectAnimator.RESTART);
|
||||
|
||||
mAnimators.add(endTrim);
|
||||
mAnimators.add(startTrim);
|
||||
mAnimators.add(rotation);
|
||||
mAnimators.add(groupRotation);
|
||||
}
|
||||
|
||||
private final Callback mCallback = new Callback() {
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.graphics.Rect;
|
||||
import android.util.MathUtils;
|
||||
import android.view.HardwareCanvas;
|
||||
import android.view.RenderNodeAnimator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -37,13 +38,16 @@ import java.util.ArrayList;
|
||||
*/
|
||||
class Ripple {
|
||||
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
|
||||
private static final TimeInterpolator DECEL_INTERPOLATOR = new DecelerateInterpolator(4);
|
||||
|
||||
private static final float GLOBAL_SPEED = 1.0f;
|
||||
private static final float WAVE_TOUCH_DOWN_ACCELERATION = 512.0f * GLOBAL_SPEED;
|
||||
private static final float WAVE_TOUCH_UP_ACCELERATION = 1024.0f * GLOBAL_SPEED;
|
||||
private static final float WAVE_OPACITY_DECAY_VELOCITY = 1.6f / GLOBAL_SPEED;
|
||||
private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0f * GLOBAL_SPEED;
|
||||
private static final float WAVE_TOUCH_UP_ACCELERATION = 3096.0f * GLOBAL_SPEED;
|
||||
private static final float WAVE_OPACITY_DECAY_VELOCITY = 1.9f / GLOBAL_SPEED;
|
||||
private static final float WAVE_OUTER_OPACITY_VELOCITY = 1.2f * GLOBAL_SPEED;
|
||||
|
||||
private static final long RIPPLE_ENTER_DELAY = 100;
|
||||
|
||||
// Hardware animators.
|
||||
private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
|
||||
private final ArrayList<RenderNodeAnimator> mPendingAnimations = new ArrayList<>();
|
||||
@@ -287,14 +291,19 @@ class Ripple {
|
||||
radius.setAutoCancel(true);
|
||||
radius.setDuration(radiusDuration);
|
||||
radius.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
radius.setStartDelay(RIPPLE_ENTER_DELAY);
|
||||
|
||||
final ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity", 1);
|
||||
cX.setAutoCancel(true);
|
||||
cX.setDuration(radiusDuration);
|
||||
cX.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
cX.setStartDelay(RIPPLE_ENTER_DELAY);
|
||||
|
||||
final ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity", 1);
|
||||
cY.setAutoCancel(true);
|
||||
cY.setDuration(radiusDuration);
|
||||
cY.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
cY.setStartDelay(RIPPLE_ENTER_DELAY);
|
||||
|
||||
final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1);
|
||||
outer.setAutoCancel(true);
|
||||
@@ -377,15 +386,15 @@ class Ripple {
|
||||
|
||||
final RenderNodeAnimator radiusAnim = new RenderNodeAnimator(mPropRadius, mOuterRadius);
|
||||
radiusAnim.setDuration(radiusDuration);
|
||||
radiusAnim.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
|
||||
|
||||
final RenderNodeAnimator xAnim = new RenderNodeAnimator(mPropX, mOuterX);
|
||||
xAnim.setDuration(radiusDuration);
|
||||
xAnim.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
xAnim.setInterpolator(DECEL_INTERPOLATOR);
|
||||
|
||||
final RenderNodeAnimator yAnim = new RenderNodeAnimator(mPropY, mOuterY);
|
||||
yAnim.setDuration(radiusDuration);
|
||||
yAnim.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
yAnim.setInterpolator(DECEL_INTERPOLATOR);
|
||||
|
||||
final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPropPaint,
|
||||
RenderNodeAnimator.PAINT_ALPHA, 0);
|
||||
@@ -439,17 +448,17 @@ class Ripple {
|
||||
final ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this, "radiusGravity", 1);
|
||||
radiusAnim.setAutoCancel(true);
|
||||
radiusAnim.setDuration(radiusDuration);
|
||||
radiusAnim.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
|
||||
|
||||
final ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity", 1);
|
||||
xAnim.setAutoCancel(true);
|
||||
xAnim.setDuration(radiusDuration);
|
||||
xAnim.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
xAnim.setInterpolator(DECEL_INTERPOLATOR);
|
||||
|
||||
final ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity", 1);
|
||||
yAnim.setAutoCancel(true);
|
||||
yAnim.setDuration(radiusDuration);
|
||||
yAnim.setInterpolator(LINEAR_INTERPOLATOR);
|
||||
yAnim.setInterpolator(DECEL_INTERPOLATOR);
|
||||
|
||||
final ObjectAnimator opacityAnim = ObjectAnimator.ofFloat(this, "opacity", 0);
|
||||
opacityAnim.setAutoCancel(true);
|
||||
|
||||
@@ -95,6 +95,9 @@ public class RippleDrawable extends LayerDrawable {
|
||||
|
||||
private final RippleState mState;
|
||||
|
||||
/** The masking layer, e.g. the layer with id R.id.mask. */
|
||||
private Drawable mMask;
|
||||
|
||||
/** The current hotspot. May be actively animating or pending entry. */
|
||||
private Ripple mHotspot;
|
||||
|
||||
@@ -261,21 +264,14 @@ public class RippleDrawable extends LayerDrawable {
|
||||
super.inflate(r, parser, attrs, theme);
|
||||
|
||||
setTargetDensity(r.getDisplayMetrics());
|
||||
|
||||
// Find the mask
|
||||
final int N = getNumberOfLayers();
|
||||
for (int i = 0; i < N; i++) {
|
||||
if (mLayerState.mChildren[i].mId == R.id.mask) {
|
||||
mState.mMask = mLayerState.mChildren[i].mDrawable;
|
||||
}
|
||||
}
|
||||
initializeFromState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setDrawableByLayerId(int id, Drawable drawable) {
|
||||
if (super.setDrawableByLayerId(id, drawable)) {
|
||||
if (id == R.id.mask) {
|
||||
mState.mMask = drawable;
|
||||
mMask = drawable;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -361,6 +357,8 @@ public class RippleDrawable extends LayerDrawable {
|
||||
} finally {
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
initializeFromState();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -527,7 +525,7 @@ public class RippleDrawable extends LayerDrawable {
|
||||
|
||||
private int drawContentLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
|
||||
final int count = mLayerState.mNum;
|
||||
if (count == 0 || (mState.mMask != null && count == 1)) {
|
||||
if (count == 0 || (mMask != null && count == 1)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -611,7 +609,7 @@ public class RippleDrawable extends LayerDrawable {
|
||||
}
|
||||
|
||||
private int drawMaskingLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
|
||||
final Drawable mask = mState.mMask;
|
||||
final Drawable mask = mMask;
|
||||
if (mask == null) {
|
||||
return -1;
|
||||
}
|
||||
@@ -667,7 +665,6 @@ public class RippleDrawable extends LayerDrawable {
|
||||
int[] mTouchThemeAttrs;
|
||||
ColorStateList mTint = null;
|
||||
PorterDuffXfermode mTintXfermode = SRC_ATOP;
|
||||
Drawable mMask;
|
||||
int mMaxRadius = RADIUS_AUTO;
|
||||
boolean mPinned = false;
|
||||
|
||||
@@ -763,8 +760,6 @@ public class RippleDrawable extends LayerDrawable {
|
||||
}
|
||||
|
||||
mState = ns;
|
||||
mState.mMask = findDrawableByLayerId(R.id.mask);
|
||||
|
||||
mLayerState = ns;
|
||||
|
||||
if (ns.mNum > 0) {
|
||||
@@ -774,5 +769,12 @@ public class RippleDrawable extends LayerDrawable {
|
||||
if (needsTheme) {
|
||||
applyTheme(theme);
|
||||
}
|
||||
|
||||
initializeFromState();
|
||||
}
|
||||
|
||||
private void initializeFromState() {
|
||||
// Initialize from constant state.
|
||||
mMask = findDrawableByLayerId(R.id.mask);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user