Bouncer: Improve push animations.

Improve the push animations of the buttons. Also improve performance by
removing RippleDrawable. The RippleDrawable was not achieving the
animations we wanted.

Bug: 218833792
Test: Tested on multiple devices
Change-Id: Iedc7a48f9be89cdfe313a26bd82d4073ea518a71
This commit is contained in:
Aaron Liu
2022-03-02 00:09:48 +00:00
parent 286c318ad2
commit df2ad47c12
4 changed files with 104 additions and 64 deletions

View File

@@ -16,14 +16,7 @@
* limitations under the License.
*/
-->
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:id="@+id/background">
<shape>
<solid android:color="?android:attr/colorControlNormal" />
<corners android:radius="10dp" />
</shape>
</item>
</ripple>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="?android:attr/colorControlNormal" />
<corners android:radius="10dp" />
</shape>

View File

@@ -16,17 +16,18 @@
package com.android.keyguard;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.view.ContextThemeWrapper;
import android.widget.TextView;
import androidx.annotation.StyleRes;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.util.Utils;
@@ -34,45 +35,100 @@ import com.android.systemui.util.Utils;
* Provides background color and radius animations for key pad buttons.
*/
class NumPadAnimator {
private AnimatorSet mAnimator;
private ValueAnimator mExpandAnimator;
private AnimatorSet mExpandAnimatorSet;
private ValueAnimator mContractAnimator;
private AnimatorSet mContractAnimatorSet;
private GradientDrawable mBackground;
private RippleDrawable mRipple;
private int mNormalColor;
private int mHighlightColor;
private int mStyle;
private static final int EXPAND_ANIMATION_MS = 100;
private static final int EXPAND_COLOR_ANIMATION_MS = 50;
private static final int CONTRACT_ANIMATION_DELAY_MS = 33;
private static final int CONTRACT_ANIMATION_MS = 417;
NumPadAnimator(Context context, final RippleDrawable drawable, @StyleRes int style) {
NumPadAnimator(Context context, final Drawable drawable, @StyleRes int style) {
this(context, drawable, style, null);
}
NumPadAnimator(Context context, final Drawable drawable, @StyleRes int style,
@Nullable TextView digitTextView) {
mStyle = style;
mRipple = (RippleDrawable) drawable.mutate();
mBackground = (GradientDrawable) mRipple.findDrawableByLayerId(R.id.background);
mBackground = (GradientDrawable) drawable;
reloadColors(context);
int textColorPrimary = com.android.settingslib.Utils
.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
int textColorPrimaryInverse = com.android.settingslib.Utils
.getColorAttrDefaultColor(context, android.R.attr.textColorPrimaryInverse);
// Actual values will be updated later, usually during an onLayout() call
mAnimator = new AnimatorSet();
mExpandAnimator = ValueAnimator.ofFloat(0f, 1f);
mExpandAnimator.setDuration(50);
mExpandAnimator.setDuration(EXPAND_ANIMATION_MS);
mExpandAnimator.setInterpolator(Interpolators.LINEAR);
mExpandAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator anim) {
mBackground.setCornerRadius((float) anim.getAnimatedValue());
mRipple.invalidateSelf();
}
mExpandAnimator.addUpdateListener(
anim -> mBackground.setCornerRadius((float) anim.getAnimatedValue()));
ValueAnimator expandBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
mNormalColor, mHighlightColor);
expandBackgroundColorAnimator.setDuration(EXPAND_COLOR_ANIMATION_MS);
expandBackgroundColorAnimator.addUpdateListener(
animator -> mBackground.setColor((int) animator.getAnimatedValue()));
ValueAnimator expandTextColorAnimator =
ValueAnimator.ofObject(new ArgbEvaluator(),
textColorPrimary, textColorPrimaryInverse);
expandTextColorAnimator.setDuration(EXPAND_COLOR_ANIMATION_MS);
expandTextColorAnimator.addUpdateListener(valueAnimator -> {
if (digitTextView != null) {
digitTextView.setTextColor((int) valueAnimator.getAnimatedValue());
}
});
mExpandAnimatorSet = new AnimatorSet();
mExpandAnimatorSet.playTogether(mExpandAnimator,
expandBackgroundColorAnimator, expandTextColorAnimator);
mContractAnimator = ValueAnimator.ofFloat(1f, 0f);
mContractAnimator.setStartDelay(33);
mContractAnimator.setDuration(417);
mContractAnimator.setStartDelay(CONTRACT_ANIMATION_DELAY_MS);
mContractAnimator.setDuration(CONTRACT_ANIMATION_MS);
mContractAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mContractAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator anim) {
mBackground.setCornerRadius((float) anim.getAnimatedValue());
mRipple.invalidateSelf();
}
mContractAnimator.addUpdateListener(
anim -> mBackground.setCornerRadius((float) anim.getAnimatedValue()));
ValueAnimator contractBackgroundColorAnimator = ValueAnimator.ofObject(new ArgbEvaluator(),
mHighlightColor, mNormalColor);
contractBackgroundColorAnimator.setStartDelay(CONTRACT_ANIMATION_DELAY_MS);
contractBackgroundColorAnimator.setDuration(CONTRACT_ANIMATION_MS);
contractBackgroundColorAnimator.addUpdateListener(
animator -> mBackground.setColor((int) animator.getAnimatedValue()));
ValueAnimator contractTextColorAnimator =
ValueAnimator.ofObject(new ArgbEvaluator(), textColorPrimaryInverse,
textColorPrimary);
contractTextColorAnimator.setStartDelay(CONTRACT_ANIMATION_DELAY_MS);
contractTextColorAnimator.setDuration(CONTRACT_ANIMATION_MS);
contractTextColorAnimator.addUpdateListener(valueAnimator -> {
if (digitTextView != null) {
digitTextView.setTextColor((int) valueAnimator.getAnimatedValue());
}
});
mAnimator.playSequentially(mExpandAnimator, mContractAnimator);
mContractAnimatorSet = new AnimatorSet();
mContractAnimatorSet.playTogether(mContractAnimator,
contractBackgroundColorAnimator, contractTextColorAnimator);
}
public void expand() {
mExpandAnimatorSet.cancel();
mContractAnimatorSet.cancel();
mExpandAnimatorSet.start();
}
public void contract() {
mExpandAnimatorSet.cancel();
mContractAnimatorSet.cancel();
mContractAnimatorSet.start();
}
void onLayout(int height) {
@@ -83,11 +139,6 @@ class NumPadAnimator {
mContractAnimator.setFloatValues(endRadius, startRadius);
}
void start() {
mAnimator.cancel();
mAnimator.start();
}
/**
* Reload colors from resources.
**/
@@ -103,7 +154,6 @@ class NumPadAnimator {
a.recycle();
mBackground.setColor(mNormalColor);
mRipple.setColor(ColorStateList.valueOf(mHighlightColor));
}
}

View File

@@ -19,8 +19,6 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.VectorDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
@@ -39,13 +37,8 @@ public class NumPadButton extends AlphaOptimizedImageButton {
public NumPadButton(Context context, AttributeSet attrs) {
super(context, attrs);
Drawable background = getBackground();
if (background instanceof RippleDrawable) {
mAnimator = new NumPadAnimator(context, (RippleDrawable) getBackground(),
attrs.getStyleAttribute());
} else {
mAnimator = null;
}
mAnimator = new NumPadAnimator(context, getBackground().mutate(),
attrs.getStyleAttribute());
}
@Override
@@ -79,8 +72,14 @@ public class NumPadButton extends AlphaOptimizedImageButton {
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN && mAnimator != null) {
mAnimator.start();
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
if (mAnimator != null) mAnimator.expand();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mAnimator != null) mAnimator.contract();
break;
}
return super.onTouchEvent(event);
}

View File

@@ -18,8 +18,6 @@ package com.android.keyguard;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -131,13 +129,8 @@ public class NumPadKey extends ViewGroup {
setContentDescription(mDigitText.getText().toString());
Drawable background = getBackground();
if (background instanceof RippleDrawable) {
mAnimator = new NumPadAnimator(context, (RippleDrawable) background,
R.style.NumPadKey);
} else {
mAnimator = null;
}
mAnimator = new NumPadAnimator(context, getBackground().mutate(),
R.style.NumPadKey, mDigitText);
}
@Override
@@ -161,11 +154,16 @@ public class NumPadKey extends ViewGroup {
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
doHapticKeyClick();
if (mAnimator != null) mAnimator.start();
switch(event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
doHapticKeyClick();
if (mAnimator != null) mAnimator.expand();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mAnimator != null) mAnimator.contract();
break;
}
return super.onTouchEvent(event);
}