From 2c464b80a3f36c6411863cd0718121769c42a992 Mon Sep 17 00:00:00 2001 From: Miranda Kephart Date: Wed, 5 Jun 2019 16:09:15 -0400 Subject: [PATCH] Use nav bar color for invocation lights Registers a listener so that the assistant invocation lights are set to the same color as the nav bar (and therefore show up on white backgrounds). Changes the stroke caps to BUTT rather than ROUND/SQUARE so that they do not overlap (since the nav bar color can be non-opaque). If the lights are explicitly set to some other color, the listener is not used. Bug: 134523274 Test: manual Change-Id: I4fc2dd4c609dcada6acdf34e269a0e62547747d0 --- .../assist/ui/DefaultUiController.java | 11 +- .../assist/ui/InvocationLightsView.java | 133 ++++++++++++++++-- .../phone/NavigationBarTransitions.java | 5 +- 3 files changed, 124 insertions(+), 25 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java index 95c136f062b50..662de3a5b5f5b 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java @@ -21,7 +21,6 @@ import static com.android.systemui.assist.AssistManager.DISMISS_REASON_INVOCATIO import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; -import android.annotation.ColorInt; import android.content.Context; import android.graphics.PixelFormat; import android.metrics.LogMaker; @@ -52,6 +51,7 @@ public class DefaultUiController implements AssistManager.UiController { private static final long ANIM_DURATION_MS = 200; protected final FrameLayout mRoot; + protected InvocationLightsView mInvocationLightsView; private final WindowManager mWindowManager; private final WindowManager.LayoutParams mLayoutParams; @@ -62,7 +62,6 @@ public class DefaultUiController implements AssistManager.UiController { private float mLastInvocationProgress = 0; private ValueAnimator mInvocationAnimator = new ValueAnimator(); - private InvocationLightsView mInvocationLightsView; public DefaultUiController(Context context) { mRoot = new FrameLayout(context); @@ -129,14 +128,6 @@ public class DefaultUiController implements AssistManager.UiController { updateAssistHandleVisibility(); } - /** - * Sets the colors of the four invocation lights, from left to right. - */ - public void setInvocationColors(@ColorInt int color1, @ColorInt int color2, - @ColorInt int color3, @ColorInt int color4) { - mInvocationLightsView.setColors(color1, color2, color3, color4); - } - protected static void logInvocationProgressMetrics( int type, float progress, boolean invocationWasInProgress) { // Logs assistant invocation start. diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java index de1d7c8c0a04a..178f4c32bb750 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java +++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java @@ -16,24 +16,34 @@ package com.android.systemui.assist.ui; +import android.animation.ArgbEvaluator; import android.annotation.ColorInt; +import android.annotation.Nullable; import android.content.Context; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.util.Log; import android.util.MathUtils; +import android.view.ContextThemeWrapper; import android.view.View; +import com.android.settingslib.Utils; +import com.android.systemui.Dependency; import com.android.systemui.R; +import com.android.systemui.statusbar.NavigationBarController; +import com.android.systemui.statusbar.phone.NavigationBarFragment; +import com.android.systemui.statusbar.phone.NavigationBarTransitions; import java.util.ArrayList; /** * Shows lights at the bottom of the phone, marking the invocation progress. */ -public class InvocationLightsView extends View { +public class InvocationLightsView extends View + implements NavigationBarTransitions.DarkIntensityListener { private static final String TAG = "InvocationLightsView"; @@ -49,9 +59,16 @@ public class InvocationLightsView extends View { // allocation on each frame. private final Path mPath = new Path(); private final int mViewHeight; + private final int mStrokeWidth; + @ColorInt + private final int mLightColor; + @ColorInt + private final int mDarkColor; // Allocate variable for screen location lookup to avoid memory alloc onDraw() private int[] mScreenLocation = new int[2]; + private boolean mRegistered = false; + private boolean mUseNavBarColor = true; public InvocationLightsView(Context context) { this(context, null); @@ -69,8 +86,8 @@ public class InvocationLightsView extends View { int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); - int strokeWidth = DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context); - mPaint.setStrokeWidth(strokeWidth); + mStrokeWidth = DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context); + mPaint.setStrokeWidth(mStrokeWidth); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeJoin(Paint.Join.MITER); mPaint.setAntiAlias(true); @@ -82,13 +99,19 @@ public class InvocationLightsView extends View { CircularCornerPathRenderer cornerPathRenderer = new CircularCornerPathRenderer( cornerRadiusBottom, cornerRadiusTop, displayWidth, displayHeight); mGuide = new PerimeterPathGuide(context, cornerPathRenderer, - strokeWidth / 2, displayWidth, displayHeight); + mStrokeWidth / 2, displayWidth, displayHeight); mViewHeight = Math.max(cornerRadiusBottom, cornerRadiusTop); - @ColorInt int lightColor = getResources().getColor(R.color.default_invocation_lights_color); + final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme); + final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme); + Context lightContext = new ContextThemeWrapper(mContext, dualToneLightTheme); + Context darkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme); + mLightColor = Utils.getColorAttrDefaultColor(lightContext, R.attr.singleToneColor); + mDarkColor = Utils.getColorAttrDefaultColor(darkContext, R.attr.singleToneColor); + for (int i = 0; i < 4; i++) { - mAssistInvocationLights.add(new EdgeLight(lightColor, 0, 0)); + mAssistInvocationLights.add(new EdgeLight(Color.TRANSPARENT, 0, 0)); } } @@ -100,6 +123,8 @@ public class InvocationLightsView extends View { if (progress == 0) { setVisibility(View.GONE); } else { + attemptRegisterNavBarListener(); + float cornerLengthNormalized = mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM_LEFT); float arcLengthNormalized = cornerLengthNormalized * MINIMUM_CORNER_RATIO; @@ -131,6 +156,21 @@ public class InvocationLightsView extends View { for (EdgeLight light : mAssistInvocationLights) { light.setLength(0); } + attemptUnregisterNavBarListener(); + } + + /** + * Sets all invocation lights to a single color. If color is null, uses the navigation bar + * color (updated when the nav bar color changes). + */ + public void setColors(@Nullable @ColorInt Integer color) { + if (color == null) { + mUseNavBarColor = true; + mPaint.setStrokeCap(Paint.Cap.BUTT); + attemptRegisterNavBarListener(); + } else { + setColors(color, color, color, color); + } } /** @@ -138,12 +178,25 @@ public class InvocationLightsView extends View { */ public void setColors(@ColorInt int color1, @ColorInt int color2, @ColorInt int color3, @ColorInt int color4) { + mUseNavBarColor = false; + attemptUnregisterNavBarListener(); mAssistInvocationLights.get(0).setColor(color1); mAssistInvocationLights.get(1).setColor(color2); mAssistInvocationLights.get(2).setColor(color3); mAssistInvocationLights.get(3).setColor(color4); } + /** + * Reacts to changes in the navigation bar color + * + * @param darkIntensity 0 is the lightest color, 1 is the darkest. + */ + @Override // NavigationBarTransitions.DarkIntensityListener + public void onDarkIntensity(float darkIntensity) { + updateDarkness(darkIntensity); + } + + @Override protected void onFinishInflate() { getLayoutParams().height = mViewHeight; @@ -166,15 +219,19 @@ public class InvocationLightsView extends View { getLocationOnScreen(mScreenLocation); canvas.translate(-mScreenLocation[0], -mScreenLocation[1]); - // if the lights are different colors, the inner ones need to be drawn last and with a - // square cap so that the join between lights is straight - mPaint.setStrokeCap(Paint.Cap.ROUND); - renderLight(mAssistInvocationLights.get(0), canvas); - renderLight(mAssistInvocationLights.get(3), canvas); + if (mUseNavBarColor) { + for (EdgeLight light : mAssistInvocationLights) { + renderLight(light, canvas); + } + } else { + mPaint.setStrokeCap(Paint.Cap.ROUND); + renderLight(mAssistInvocationLights.get(0), canvas); + renderLight(mAssistInvocationLights.get(3), canvas); - mPaint.setStrokeCap(Paint.Cap.SQUARE); - renderLight(mAssistInvocationLights.get(1), canvas); - renderLight(mAssistInvocationLights.get(2), canvas); + mPaint.setStrokeCap(Paint.Cap.BUTT); + renderLight(mAssistInvocationLights.get(1), canvas); + renderLight(mAssistInvocationLights.get(2), canvas); + } } protected void setLight(int index, float offset, float length) { @@ -185,10 +242,58 @@ public class InvocationLightsView extends View { mAssistInvocationLights.get(index).setLength(length); } + /** + * Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color + * appropriately. Intention is to match the home handle color. + */ + protected void updateDarkness(float darkIntensity) { + if (mUseNavBarColor) { + @ColorInt int invocationColor = (int) ArgbEvaluator.getInstance().evaluate( + darkIntensity, mLightColor, mDarkColor); + for (EdgeLight light : mAssistInvocationLights) { + light.setColor(invocationColor); + } + invalidate(); + } + } + private void renderLight(EdgeLight light, Canvas canvas) { mGuide.strokeSegment(mPath, light.getOffset(), light.getOffset() + light.getLength()); mPaint.setColor(light.getColor()); canvas.drawPath(mPath, mPaint); } + private void attemptRegisterNavBarListener() { + if (!mRegistered) { + NavigationBarController controller = Dependency.get(NavigationBarController.class); + if (controller == null) { + return; + } + + NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment(); + if (navBar == null) { + return; + } + + updateDarkness(navBar.getBarTransitions().addDarkIntensityListener(this)); + mRegistered = true; + } + } + + private void attemptUnregisterNavBarListener() { + if (mRegistered) { + NavigationBarController controller = Dependency.get(NavigationBarController.class); + if (controller == null) { + return; + } + + NavigationBarFragment navBar = controller.getDefaultNavigationBarFragment(); + if (navBar == null) { + return; + } + + navBar.getBarTransitions().removeDarkIntensityListener(this); + mRegistered = false; + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java index 2b5a28e600828..23cc0fc51ec03 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java @@ -213,9 +213,12 @@ public final class NavigationBarTransitions extends BarTransitions implements /** * Register {@code listener} to be notified when the color of nav bar elements changes. + * + * Returns the current nav bar color. */ - public void addDarkIntensityListener(DarkIntensityListener listener) { + public float addDarkIntensityListener(DarkIntensityListener listener) { mDarkIntensityListeners.add(listener); + return mLightTransitionsController.getCurrentDarkIntensity(); } /**