Color extraction on scrims
Consuming color extraction library to add wallpaper colors to sysui scrims. Handles both lock screen and notification shade. Bug: 36856508 Bug: 37013527 Test: runtest --path frameworks/base/packages/SystemUI/tests/src/com/android/systemui/statusbar/ScrimViewTest.java Change-Id: I8d964c978a766243d90bbfb3432d19eebf1a2056
This commit is contained in:
@@ -37,7 +37,8 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
|
||||
android-support-v7-mediarouter \
|
||||
android-support-v7-palette \
|
||||
android-support-v14-preference \
|
||||
android-support-v17-leanback
|
||||
android-support-v17-leanback \
|
||||
colorextraction
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
SystemUI-tags \
|
||||
|
||||
@@ -19,39 +19,52 @@ package com.android.systemui.statusbar;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.Interpolator;
|
||||
import com.android.systemui.R;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||
|
||||
import com.google.android.colorextraction.ColorExtractor;
|
||||
import com.google.android.colorextraction.drawable.GradientDrawable;
|
||||
|
||||
/**
|
||||
* A view which can draw a scrim
|
||||
*/
|
||||
public class ScrimView extends View
|
||||
{
|
||||
private final Paint mPaint = new Paint();
|
||||
private int mScrimColor;
|
||||
private boolean mIsEmpty = true;
|
||||
public class ScrimView extends View implements ConfigurationController.ConfigurationListener {
|
||||
private static final String TAG = "ScrimView";
|
||||
private final ColorExtractor.GradientColors mColors;
|
||||
private boolean mDrawAsSrc;
|
||||
private float mViewAlpha = 1.0f;
|
||||
private ValueAnimator mAlphaAnimator;
|
||||
private Rect mExcludedRect = new Rect();
|
||||
private boolean mHasExcludedArea;
|
||||
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
|
||||
= new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
mViewAlpha = (float) animation.getAnimatedValue();
|
||||
invalidate();
|
||||
private Drawable mDrawable;
|
||||
private PorterDuffColorFilter mColorFilter;
|
||||
private int mTintColor;
|
||||
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener = animation -> {
|
||||
if (mDrawable == null) {
|
||||
Log.w(TAG, "Trying to animate null drawable");
|
||||
return;
|
||||
}
|
||||
mDrawable.setAlpha((int) (255 * (float) animation.getAnimatedValue()));
|
||||
};
|
||||
private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
@@ -76,72 +89,134 @@ public class ScrimView extends View
|
||||
public ScrimView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
|
||||
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ScrimView);
|
||||
mDrawable = new GradientDrawable(context);
|
||||
mDrawable.setCallback(this);
|
||||
mColors = new ColorExtractor.GradientColors();
|
||||
updateScreenSize();
|
||||
|
||||
try {
|
||||
mScrimColor = ta.getColor(R.styleable.ScrimView_scrimColor, Color.BLACK);
|
||||
} finally {
|
||||
ta.recycle();
|
||||
}
|
||||
// We need to know about configuration changes to update the gradient size
|
||||
// since it's independent from view bounds.
|
||||
ConfigurationController config = Dependency.get(ConfigurationController.class);
|
||||
config.addCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (mDrawAsSrc || (!mIsEmpty && mViewAlpha > 0f)) {
|
||||
PorterDuff.Mode mode = mDrawAsSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
|
||||
int color = getScrimColorWithAlpha();
|
||||
if (mDrawAsSrc || mDrawable.getAlpha() > 0) {
|
||||
if (!mHasExcludedArea) {
|
||||
canvas.drawColor(color, mode);
|
||||
mDrawable.draw(canvas);
|
||||
} else {
|
||||
mPaint.setColor(color);
|
||||
if (mExcludedRect.top > 0) {
|
||||
canvas.drawRect(0, 0, getWidth(), mExcludedRect.top, mPaint);
|
||||
canvas.save();
|
||||
canvas.clipRect(0, 0, getWidth(), mExcludedRect.top);
|
||||
mDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
if (mExcludedRect.left > 0) {
|
||||
canvas.drawRect(0, mExcludedRect.top, mExcludedRect.left, mExcludedRect.bottom,
|
||||
mPaint);
|
||||
canvas.save();
|
||||
canvas.clipRect(0, mExcludedRect.top, mExcludedRect.left,
|
||||
mExcludedRect.bottom);
|
||||
mDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
if (mExcludedRect.right < getWidth()) {
|
||||
canvas.drawRect(mExcludedRect.right,
|
||||
mExcludedRect.top,
|
||||
getWidth(),
|
||||
mExcludedRect.bottom,
|
||||
mPaint);
|
||||
canvas.save();
|
||||
canvas.clipRect(mExcludedRect.right, mExcludedRect.top, getWidth(),
|
||||
mExcludedRect.bottom);
|
||||
mDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
if (mExcludedRect.bottom < getHeight()) {
|
||||
canvas.drawRect(0, mExcludedRect.bottom, getWidth(), getHeight(), mPaint);
|
||||
canvas.save();
|
||||
canvas.clipRect(0, mExcludedRect.bottom, getWidth(), getHeight());
|
||||
mDrawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getScrimColorWithAlpha() {
|
||||
int color = mScrimColor;
|
||||
color = Color.argb((int) (Color.alpha(color) * mViewAlpha), Color.red(color),
|
||||
Color.green(color), Color.blue(color));
|
||||
return color;
|
||||
public void setDrawable(Drawable drawable) {
|
||||
mDrawable = drawable;
|
||||
mDrawable.setCallback(this);
|
||||
mDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom());
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(@NonNull Drawable drawable) {
|
||||
super.invalidateDrawable(drawable);
|
||||
if (drawable == mDrawable) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setDrawAsSrc(boolean asSrc) {
|
||||
mDrawAsSrc = asSrc;
|
||||
mPaint.setXfermode(new PorterDuffXfermode(mDrawAsSrc ? PorterDuff.Mode.SRC
|
||||
: PorterDuff.Mode.SRC_OVER));
|
||||
invalidate();
|
||||
PorterDuff.Mode mode = asSrc ? PorterDuff.Mode.SRC : PorterDuff.Mode.SRC_OVER;
|
||||
mDrawable.setXfermode(new PorterDuffXfermode(mode));
|
||||
}
|
||||
|
||||
public void setScrimColor(int color) {
|
||||
if (color != mScrimColor) {
|
||||
mIsEmpty = Color.alpha(color) == 0;
|
||||
mScrimColor = color;
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (changed) {
|
||||
mDrawable.setBounds(left, top, right, bottom);
|
||||
invalidate();
|
||||
if (mChangeRunnable != null) {
|
||||
mChangeRunnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getScrimColor() {
|
||||
return mScrimColor;
|
||||
public void setColors(@NonNull ColorExtractor.GradientColors colors) {
|
||||
if (colors == null) {
|
||||
throw new IllegalArgumentException("Colors cannot be null");
|
||||
}
|
||||
if (mColors.equals(colors)) {
|
||||
return;
|
||||
}
|
||||
mColors.set(colors);
|
||||
updateColorWithTint();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
Drawable getDrawable() {
|
||||
return mDrawable;
|
||||
}
|
||||
|
||||
public void setTint(int color) {
|
||||
if (mTintColor == color) {
|
||||
return;
|
||||
}
|
||||
mTintColor = color;
|
||||
updateColorWithTint();
|
||||
}
|
||||
|
||||
private void updateColorWithTint() {
|
||||
if (mDrawable instanceof GradientDrawable) {
|
||||
// Optimization to blend colors and avoid a color filter
|
||||
GradientDrawable drawable = (GradientDrawable) mDrawable;
|
||||
float tintAmount = Color.alpha(mTintColor) / 255f;
|
||||
int mainTinted = ColorUtils.blendARGB(mColors.getMainColor(), mTintColor,
|
||||
tintAmount);
|
||||
int secondaryTinted = ColorUtils.blendARGB(mColors.getSecondaryColor(), mTintColor,
|
||||
tintAmount);
|
||||
drawable.setColors(mainTinted, secondaryTinted, false);
|
||||
} else {
|
||||
if (mColorFilter == null) {
|
||||
mColorFilter = new PorterDuffColorFilter(mTintColor, PorterDuff.Mode.SRC_OVER);
|
||||
} else {
|
||||
mColorFilter.setColor(mTintColor);
|
||||
}
|
||||
mDrawable.setColorFilter(Color.alpha(mTintColor) == 0 ? null : mColorFilter);
|
||||
mDrawable.invalidateSelf();
|
||||
}
|
||||
|
||||
if (mChangeRunnable != null) {
|
||||
mChangeRunnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTint() {
|
||||
return mTintColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,23 +225,30 @@ public class ScrimView extends View
|
||||
}
|
||||
|
||||
public void setViewAlpha(float alpha) {
|
||||
if (mAlphaAnimator != null) {
|
||||
mAlphaAnimator.cancel();
|
||||
}
|
||||
if (alpha != mViewAlpha) {
|
||||
mViewAlpha = alpha;
|
||||
invalidate();
|
||||
|
||||
if (mAlphaAnimator != null) {
|
||||
mAlphaAnimator.cancel();
|
||||
}
|
||||
|
||||
mDrawable.setAlpha((int) (255 * alpha));
|
||||
if (mChangeRunnable != null) {
|
||||
mChangeRunnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
float getViewAlpha() {
|
||||
return mViewAlpha;
|
||||
}
|
||||
|
||||
public void animateViewAlpha(float alpha, long durationOut, Interpolator interpolator) {
|
||||
if (mAlphaAnimator != null) {
|
||||
mAlphaAnimator.cancel();
|
||||
}
|
||||
mAlphaAnimator = ValueAnimator.ofFloat(mViewAlpha, alpha);
|
||||
mAlphaAnimator = ValueAnimator.ofFloat(getViewAlpha(), alpha);
|
||||
mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
|
||||
mAlphaAnimator.addListener(mClearAnimatorListener);
|
||||
mAlphaAnimator.setInterpolator(interpolator);
|
||||
@@ -193,4 +275,25 @@ public class ScrimView extends View
|
||||
public void setChangeRunnable(Runnable changeRunnable) {
|
||||
mChangeRunnable = changeRunnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigChanged(Configuration newConfig) {
|
||||
updateScreenSize();
|
||||
}
|
||||
|
||||
private void updateScreenSize() {
|
||||
if (mDrawable instanceof GradientDrawable) {
|
||||
WindowManager wm = mContext.getSystemService(WindowManager.class);
|
||||
if (wm == null) {
|
||||
Log.w(TAG, "Can't resize gradient drawable to fit the screen");
|
||||
return;
|
||||
}
|
||||
Display display = wm.getDefaultDisplay();
|
||||
if (display != null) {
|
||||
Point size = new Point();
|
||||
display.getRealSize(size);
|
||||
((GradientDrawable) mDrawable).setScreenSize(size.x, size.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,12 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -30,6 +33,7 @@ import android.view.ViewTreeObserver;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.view.animation.PathInterpolator;
|
||||
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.ExpandableNotificationRow;
|
||||
@@ -38,12 +42,14 @@ import com.android.systemui.statusbar.ScrimView;
|
||||
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
|
||||
import com.android.systemui.statusbar.stack.ViewState;
|
||||
|
||||
import com.google.android.colorextraction.ColorExtractor;
|
||||
|
||||
/**
|
||||
* Controls both the scrim behind the notifications and in front of the notifications (when a
|
||||
* security method gets shown).
|
||||
*/
|
||||
public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
OnHeadsUpChangedListener {
|
||||
OnHeadsUpChangedListener, ColorExtractor.OnColorsChangedListener {
|
||||
public static final long ANIMATION_DURATION = 220;
|
||||
public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR
|
||||
= new PathInterpolator(0f, 0, 0.7f, 1f);
|
||||
@@ -61,11 +67,16 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
|
||||
private final LightBarController mLightBarController;
|
||||
protected final ScrimView mScrimBehind;
|
||||
private final ScrimView mScrimInFront;
|
||||
protected final ScrimView mScrimInFront;
|
||||
private final UnlockMethodCache mUnlockMethodCache;
|
||||
private final View mHeadsUpScrim;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
|
||||
private final ColorExtractor mColorExtractor;
|
||||
private ColorExtractor.GradientColors mLockColors;
|
||||
private ColorExtractor.GradientColors mSystemColors;
|
||||
private boolean mNeedsDrawableColorUpdate;
|
||||
|
||||
protected float mScrimBehindAlpha;
|
||||
protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
|
||||
protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING;
|
||||
@@ -98,6 +109,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
private boolean mSkipFirstFrame;
|
||||
private boolean mDontAnimateBouncerChanges;
|
||||
private boolean mKeyguardFadingOutInProgress;
|
||||
private boolean mAnimatingDozeUnlock;
|
||||
private ValueAnimator mKeyguardFadeoutAnimation;
|
||||
|
||||
public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
|
||||
@@ -111,12 +123,22 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
mLightBarController = lightBarController;
|
||||
mScrimBehindAlpha = context.getResources().getFloat(R.dimen.scrim_behind_alpha);
|
||||
|
||||
mColorExtractor = new ColorExtractor(context);
|
||||
mColorExtractor.setListener(this);
|
||||
mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK);
|
||||
mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM);
|
||||
mNeedsDrawableColorUpdate = true;
|
||||
|
||||
updateHeadsUpScrim(false);
|
||||
updateScrims();
|
||||
}
|
||||
|
||||
public void setKeyguardShowing(boolean showing) {
|
||||
mKeyguardShowing = showing;
|
||||
|
||||
// Showing/hiding the keyguard means that scrim colors
|
||||
// will probably have to be switched
|
||||
mNeedsDrawableColorUpdate = true;
|
||||
scheduleUpdate();
|
||||
}
|
||||
|
||||
@@ -157,6 +179,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
|
||||
public void setWakeAndUnlocking() {
|
||||
mWakeAndUnlocking = true;
|
||||
mAnimatingDozeUnlock = true;
|
||||
scheduleUpdate();
|
||||
}
|
||||
|
||||
@@ -192,7 +215,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
|
||||
public void animateKeyguardUnoccluding(long duration) {
|
||||
mAnimateChange = false;
|
||||
setScrimBehindColor(0f);
|
||||
setScrimBehindAlpha(0f);
|
||||
mAnimateChange = true;
|
||||
scheduleUpdate();
|
||||
mDurationOverride = duration;
|
||||
@@ -246,23 +269,35 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
}
|
||||
|
||||
protected void updateScrims() {
|
||||
if (mAnimateKeyguardFadingOut || mForceHideScrims) {
|
||||
setScrimInFrontColor(0f);
|
||||
setScrimBehindColor(0f);
|
||||
} else if (mWakeAndUnlocking) {
|
||||
|
||||
// Make sure we have the right gradients
|
||||
if (mNeedsDrawableColorUpdate) {
|
||||
mNeedsDrawableColorUpdate = false;
|
||||
if (mKeyguardShowing) {
|
||||
mScrimInFront.setColors(mLockColors);
|
||||
mScrimBehind.setColors(mLockColors);
|
||||
} else {
|
||||
mScrimInFront.setColors(mSystemColors);
|
||||
mScrimBehind.setColors(mSystemColors);
|
||||
}
|
||||
}
|
||||
|
||||
if (mAnimateKeyguardFadingOut || mForceHideScrims) {
|
||||
setScrimInFrontAlpha(0f);
|
||||
setScrimBehindAlpha(0f);
|
||||
} else if (mWakeAndUnlocking) {
|
||||
// During wake and unlock, we first hide everything behind a black scrim, which then
|
||||
// gets faded out from animateKeyguardFadingOut.
|
||||
if (mDozing) {
|
||||
setScrimInFrontColor(0f);
|
||||
setScrimBehindColor(1f);
|
||||
setScrimInFrontAlpha(0f);
|
||||
setScrimBehindAlpha(1f);
|
||||
} else {
|
||||
setScrimInFrontColor(1f);
|
||||
setScrimBehindColor(0f);
|
||||
setScrimInFrontAlpha(1f);
|
||||
setScrimBehindAlpha(0f);
|
||||
}
|
||||
} else if (!mKeyguardShowing && !mBouncerShowing) {
|
||||
updateScrimNormal();
|
||||
setScrimInFrontColor(0);
|
||||
setScrimInFrontAlpha(0);
|
||||
} else {
|
||||
updateScrimKeyguard();
|
||||
}
|
||||
@@ -275,18 +310,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
float fraction = 1 - behindFraction;
|
||||
fraction = (float) Math.pow(fraction, 0.8f);
|
||||
behindFraction = (float) Math.pow(behindFraction, 0.8f);
|
||||
setScrimInFrontColor(fraction * getScrimInFrontAlpha());
|
||||
setScrimBehindColor(behindFraction * mScrimBehindAlphaKeyguard);
|
||||
setScrimInFrontAlpha(fraction * getScrimInFrontAlpha());
|
||||
setScrimBehindAlpha(behindFraction * mScrimBehindAlphaKeyguard);
|
||||
} else if (mBouncerShowing && !mBouncerIsKeyguard) {
|
||||
setScrimInFrontColor(getScrimInFrontAlpha());
|
||||
setScrimInFrontAlpha(getScrimInFrontAlpha());
|
||||
updateScrimNormal();
|
||||
} else if (mBouncerShowing) {
|
||||
setScrimInFrontColor(0f);
|
||||
setScrimBehindColor(mScrimBehindAlpha);
|
||||
setScrimInFrontAlpha(0f);
|
||||
setScrimBehindAlpha(mScrimBehindAlpha);
|
||||
} else {
|
||||
float fraction = Math.max(0, Math.min(mFraction, 1));
|
||||
setScrimInFrontColor(0f);
|
||||
setScrimBehindColor(fraction
|
||||
setScrimInFrontAlpha(0f);
|
||||
setScrimBehindAlpha(fraction
|
||||
* (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
|
||||
+ mScrimBehindAlphaUnlocking);
|
||||
}
|
||||
@@ -297,30 +332,29 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
// let's start this 20% of the way down the screen
|
||||
frac = frac * 1.2f - 0.2f;
|
||||
if (frac <= 0) {
|
||||
setScrimBehindColor(0);
|
||||
setScrimBehindAlpha(0);
|
||||
} else {
|
||||
// woo, special effects
|
||||
final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
|
||||
setScrimBehindColor(k * mScrimBehindAlpha);
|
||||
setScrimBehindAlpha(k * mScrimBehindAlpha);
|
||||
}
|
||||
}
|
||||
|
||||
private void setScrimBehindColor(float alpha) {
|
||||
setScrimColor(mScrimBehind, alpha);
|
||||
private void setScrimBehindAlpha(float alpha) {
|
||||
setScrimAlpha(mScrimBehind, alpha);
|
||||
}
|
||||
|
||||
private void setScrimInFrontColor(float alpha) {
|
||||
setScrimColor(mScrimInFront, alpha);
|
||||
private void setScrimInFrontAlpha(float alpha) {
|
||||
setScrimAlpha(mScrimInFront, alpha);
|
||||
if (alpha == 0f) {
|
||||
mScrimInFront.setClickable(false);
|
||||
} else {
|
||||
|
||||
// Eat touch events (unless dozing).
|
||||
mScrimInFront.setClickable(!mDozing);
|
||||
}
|
||||
}
|
||||
|
||||
private void setScrimColor(View scrim, float alpha) {
|
||||
private void setScrimAlpha(View scrim, float alpha) {
|
||||
updateScrim(mAnimateChange, scrim, alpha, getCurrentScrimAlpha(scrim));
|
||||
}
|
||||
|
||||
@@ -346,15 +380,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateScrimColor(View scrim) {
|
||||
private void updateScrimColor(View scrim) {
|
||||
float alpha1 = getCurrentScrimAlpha(scrim);
|
||||
if (scrim instanceof ScrimView) {
|
||||
float alpha2 = getDozeAlpha(scrim);
|
||||
float alpha = 1 - (1 - alpha1) * (1 - alpha2);
|
||||
ScrimView scrimView = (ScrimView) scrim;
|
||||
float dozeAlpha = getDozeAlpha(scrim);
|
||||
float alpha = 1 - (1 - alpha1) * (1 - dozeAlpha);
|
||||
alpha = Math.max(0, Math.min(1.0f, alpha));
|
||||
int baseColor = ((ScrimView) scrim).getScrimColor();
|
||||
((ScrimView) scrim).setScrimColor(
|
||||
ColorUtils.setAlphaComponent(baseColor, (int) (alpha * 255)));
|
||||
scrimView.setViewAlpha(alpha);
|
||||
|
||||
int dozeTint = Color.TRANSPARENT;
|
||||
if (mAnimatingDozeUnlock || mDozing) {
|
||||
dozeTint = Color.BLACK;
|
||||
}
|
||||
scrimView.setTint(dozeTint);
|
||||
} else {
|
||||
scrim.setAlpha(alpha1);
|
||||
}
|
||||
@@ -363,13 +402,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
private void startScrimAnimation(final View scrim, float target) {
|
||||
float current = getCurrentScrimAlpha(scrim);
|
||||
ValueAnimator anim = ValueAnimator.ofFloat(current, target);
|
||||
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(ValueAnimator animation) {
|
||||
float alpha = (float) animation.getAnimatedValue();
|
||||
setCurrentScrimAlpha(scrim, alpha);
|
||||
updateScrimColor(scrim);
|
||||
}
|
||||
anim.addUpdateListener(animation -> {
|
||||
float alpha = (float) animation.getAnimatedValue();
|
||||
setCurrentScrimAlpha(scrim, alpha);
|
||||
updateScrimColor(scrim);
|
||||
});
|
||||
anim.setInterpolator(getInterpolator());
|
||||
anim.setStartDelay(mAnimationDelay);
|
||||
@@ -384,6 +420,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
if (mKeyguardFadingOutInProgress) {
|
||||
mKeyguardFadeoutAnimation = null;
|
||||
mKeyguardFadingOutInProgress = false;
|
||||
mAnimatingDozeUnlock = false;
|
||||
}
|
||||
scrim.setTag(TAG_KEY_ANIM, null);
|
||||
scrim.setTag(TAG_KEY_ANIM_TARGET, null);
|
||||
@@ -436,6 +473,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
mOnAnimationFinished = null;
|
||||
}
|
||||
mKeyguardFadingOutInProgress = false;
|
||||
if (!mWakeAndUnlocking || force)
|
||||
mAnimatingDozeUnlock = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,8 +598,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
mScrimBehind.setExcludedArea(area);
|
||||
}
|
||||
|
||||
public int getScrimBehindColor() {
|
||||
return mScrimBehind.getScrimColorWithAlpha();
|
||||
public int getBackgroundColor() {
|
||||
int color = mLockColors.getMainColor();
|
||||
return Color.argb((int) (mScrimBehind.getAlpha() * Color.alpha(color)),
|
||||
Color.red(color), Color.green(color), Color.blue(color));
|
||||
}
|
||||
|
||||
public void setScrimBehindChangeRunnable(Runnable changeRunnable) {
|
||||
@@ -577,4 +618,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener,
|
||||
public void setCurrentUser(int currentUser) {
|
||||
// Don't care in the base class.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onColorsChanged(ColorExtractor.GradientColors colors, int which) {
|
||||
if ((which & WallpaperManager.FLAG_LOCK) != 0) {
|
||||
mLockColors = colors;
|
||||
mNeedsDrawableColorUpdate = true;
|
||||
scheduleUpdate();
|
||||
}
|
||||
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
|
||||
mSystemColors = colors;
|
||||
mNeedsDrawableColorUpdate = true;
|
||||
scheduleUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.OverScroller;
|
||||
import android.widget.ScrollView;
|
||||
|
||||
import com.android.internal.logging.MetricsLogger;
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.systemui.ExpandHelper;
|
||||
@@ -87,6 +88,8 @@ import com.android.systemui.statusbar.phone.ScrimController;
|
||||
import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.policy.ScrollAdapter;
|
||||
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -485,16 +488,8 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
float alpha = BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
|
||||
alpha *= mBackgroundFadeAmount;
|
||||
// We need to manually blend in the background color
|
||||
int scrimColor = mScrimController.getScrimBehindColor();
|
||||
// SRC_OVER blending Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc
|
||||
float alphaInv = 1 - alpha;
|
||||
int color = Color.argb((int) (alpha * 255 + alphaInv * Color.alpha(scrimColor)),
|
||||
(int) (mBackgroundFadeAmount * Color.red(mBgColor)
|
||||
+ alphaInv * Color.red(scrimColor)),
|
||||
(int) (mBackgroundFadeAmount * Color.green(mBgColor)
|
||||
+ alphaInv * Color.green(scrimColor)),
|
||||
(int) (mBackgroundFadeAmount * Color.blue(mBgColor)
|
||||
+ alphaInv * Color.blue(scrimColor)));
|
||||
int scrimColor = mScrimController.getBackgroundColor();
|
||||
int color = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
|
||||
if (mCachedBackgroundColor != color) {
|
||||
mCachedBackgroundColor = color;
|
||||
mBackgroundPaint.setColor(color);
|
||||
@@ -4074,12 +4069,7 @@ public class NotificationStackScrollLayout extends ViewGroup
|
||||
|
||||
public void setScrimController(ScrimController scrimController) {
|
||||
mScrimController = scrimController;
|
||||
mScrimController.setScrimBehindChangeRunnable(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateBackgroundDimming();
|
||||
}
|
||||
});
|
||||
mScrimController.setScrimBehindChangeRunnable(this::updateBackgroundDimming);
|
||||
}
|
||||
|
||||
public void forceNoOverlappingRendering(boolean force) {
|
||||
|
||||
@@ -43,7 +43,8 @@ LOCAL_STATIC_ANDROID_LIBRARIES := \
|
||||
android-support-v7-appcompat \
|
||||
android-support-v7-mediarouter \
|
||||
android-support-v14-preference \
|
||||
android-support-v17-leanback
|
||||
android-support-v17-leanback \
|
||||
colorextraction
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES := \
|
||||
metrics-helper-lib \
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.statusbar;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffColorFilter;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import android.graphics.drawable.VectorDrawable;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.ScrimView;
|
||||
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class ScrimViewTest extends SysuiTestCase {
|
||||
|
||||
ScrimView mView;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mView = new ScrimView(getContext());
|
||||
mView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
|
||||
mView.layout(0, 0, 1920, 1080);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetDrawable_UpdateDrawable() {
|
||||
Drawable drawable = new ColorDrawable(Color.GREEN);
|
||||
mView.setDrawable(drawable);
|
||||
assertEquals(drawable, mView.getDrawable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetViewAlpha_propagatesToDrawable() {
|
||||
float alpha = 0.5f;
|
||||
mView.setViewAlpha(alpha);
|
||||
assertEquals(mView.getViewAlpha(), alpha);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnDraw_ExcludeRectDrawable() {
|
||||
mView.setExcludedArea(new Rect(10, 10, 20, 20));
|
||||
Canvas canvas = mock(Canvas.class);
|
||||
mView.onDraw(canvas);
|
||||
// One time for each rect side
|
||||
verify(canvas, times(4)).clipRect(anyInt(), anyInt(), anyInt(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setTint_set() {
|
||||
int tint = Color.BLUE;
|
||||
mView.setTint(tint);
|
||||
assertEquals(mView.getTint(), tint);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user