Merge "Adjustments to handles visuals and behavior" into qt-dev

This commit is contained in:
Matt Casey
2019-05-30 00:01:33 +00:00
committed by Android (Google) Code Review
8 changed files with 305 additions and 72 deletions

View File

@@ -1,25 +0,0 @@
<!--
Copyright (C) 2019 The Android Open Source Project
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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="12dp"
android:width="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
<path android:fillColor="#00000000"
android:pathData="M 1.18 10.65 C 1.18 5.58 5.41 1.18 10.65 1.18"
android:strokeColor="#000"
android:strokeLineCap="round"
android:strokeWidth="1.3" />
</vector>

View File

@@ -18,36 +18,30 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.android.systemui.CornerHandleView
android:id="@+id/assist_hint_left"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="left|top"
android:visibility="gone"/>
<com.android.systemui.CornerHandleView
android:id="@+id/assist_hint_right"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_gravity="right|bottom"
android:visibility="gone"/>
<ImageView
android:id="@+id/left"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_gravity="left|top"
android:tint="#ff000000"
android:src="@drawable/rounded" />
android:src="@drawable/rounded"/>
<ImageView
android:id="@+id/right"
android:layout_width="12dp"
android:layout_height="12dp"
android:tint="#ff000000"
android:layout_gravity="right|bottom"
android:src="@drawable/rounded" />
<ImageView
android:id="@+id/assist_hint_left"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="6dp"
android:layout_gravity="left|top"
android:src="@drawable/corner_gesture_hint"
android:tint="#ffffffff"
android:visibility="gone" />
<ImageView
android:id="@+id/assist_hint_right"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="6dp"
android:layout_gravity="right|bottom"
android:src="@drawable/corner_gesture_hint"
android:tint="#ffffffff"
android:visibility="gone" />
android:src="@drawable/rounded"/>
</com.android.systemui.RegionInterceptingFrameLayout>

View File

@@ -0,0 +1,143 @@
/*
* Copyright (C) 2019 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;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.ContextThemeWrapper;
import android.view.View;
import com.android.settingslib.Utils;
/**
* CornerHandleView draws an inset arc intended to be displayed within the screen decoration
* corners.
*/
public class CornerHandleView extends View {
private static final boolean ALLOW_TUNING = false;
private static final int ANGLE_DEGREES = 50;
public static final int MARGIN_DP = 11;
public static final int RADIUS_DP = 37;
public static final float STROKE_DP = 2.5f;
private Paint mPaint;
private int mLightColor;
private int mDarkColor;
private RectF mOval;
public CornerHandleView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(getStrokePx());
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);
updateOval();
}
/**
* Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
* approriately. Intention is to match the home handle color.
*/
public void updateDarkness(float darkIntensity) {
mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
mLightColor,
mDarkColor));
invalidate();
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (ALLOW_TUNING) {
mPaint.setStrokeWidth(getStrokePx());
updateOval();
}
canvas.drawArc(mOval, 180 + ((90 - getAngle()) / 2), getAngle(), false,
mPaint);
}
// TODO(b/133834204): Remove tweaking of corner handles
private static float convertDpToPixel(float dp, Context context) {
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi
/ DisplayMetrics.DENSITY_DEFAULT);
}
private void updateOval() {
mOval = new RectF(getMarginPx() - (getStrokePx() / 2.f),
getMarginPx() - (getStrokePx() / 2.f),
getMarginPx() + (2 * (getRadiusPx()) + (getStrokePx() / 2.f)),
getMarginPx() + 2 * getRadiusPx() + (getStrokePx() / 2.f));
}
private int getAngle() {
if (ALLOW_TUNING) {
return SystemProperties.getInt("CORNER_HANDLE_ANGLE_DEGREES", ANGLE_DEGREES);
} else {
return ANGLE_DEGREES;
}
}
private int getMarginPx() {
if (ALLOW_TUNING) {
return SystemProperties.getInt("CORNER_HANDLE_MARGIN_PX",
(int) convertDpToPixel(MARGIN_DP, getContext()));
} else {
return (int) convertDpToPixel(MARGIN_DP, getContext());
}
}
private int getRadiusPx() {
if (ALLOW_TUNING) {
return SystemProperties.getInt("CORNER_HANDLE_RADIUS_PX",
(int) convertDpToPixel(RADIUS_DP, getContext()));
} else {
return (int) convertDpToPixel(RADIUS_DP, getContext());
}
}
private int getStrokePx() {
if (ALLOW_TUNING) {
return SystemProperties.getInt("CORNER_HANDLE_STROKE_PX",
(int) convertDpToPixel(STROKE_DP, getContext()));
} else {
return (int) convertDpToPixel(STROKE_DP, getContext());
}
}
}

View File

@@ -60,6 +60,12 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.OvershootInterpolator;
import android.view.animation.PathInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -72,6 +78,7 @@ import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.NavigationBarTransitions;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.tuner.TunablePadding;
import com.android.systemui.tuner.TunerService;
@@ -85,7 +92,8 @@ import java.util.List;
* An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
* for antialiasing and emulation purposes.
*/
public class ScreenDecorations extends SystemUI implements Tunable {
public class ScreenDecorations extends SystemUI implements Tunable,
NavigationBarTransitions.DarkIntensityListener {
private static final boolean DEBUG = false;
private static final String TAG = "ScreenDecorations";
@@ -93,13 +101,17 @@ public class ScreenDecorations extends SystemUI implements Tunable {
public static final String PADDING = "sysui_rounded_content_padding";
private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
private static final boolean VERBOSE = false;
private DisplayManager mDisplayManager;
private DisplayManager.DisplayListener mDisplayListener;
@VisibleForTesting protected int mRoundedDefault;
@VisibleForTesting protected int mRoundedDefaultTop;
@VisibleForTesting protected int mRoundedDefaultBottom;
@VisibleForTesting
protected int mRoundedDefault;
@VisibleForTesting
protected int mRoundedDefaultTop;
@VisibleForTesting
protected int mRoundedDefaultBottom;
private View mOverlay;
private View mBottomOverlay;
private float mDensity;
@@ -111,6 +123,8 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private SecureSetting mColorInversionSetting;
private boolean mPendingRotationChange;
private Handler mHandler;
private boolean mAssistHintBlocked = false;
private boolean mIsReceivingNavBarColor = false;
/**
* Converts a set of {@link Rect}s into a {@link Region}
@@ -137,15 +151,32 @@ public class ScreenDecorations extends SystemUI implements Tunable {
putComponent(ScreenDecorations.class, this);
}
private void fade(View view, boolean fadeIn) {
private void fade(View view, boolean fadeIn, boolean isLeft) {
if (fadeIn) {
view.animate().cancel();
view.setAlpha(0f);
view.setAlpha(1f);
view.setVisibility(View.VISIBLE);
view.animate().alpha(1f);
AnimationSet anim = new AnimationSet(true);
anim.setDuration(900);
Animation scaleAnimation = new ScaleAnimation(2f, 1f, 2f, 1f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
anim.addAnimation(scaleAnimation);
anim.setInterpolator(new PathInterpolator(0.02f, 0.44f, 0.67f, 1.00f));
Animation translateAnimation = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_SELF, isLeft ? -0.2f : 0.2f,
TranslateAnimation.RELATIVE_TO_SELF,
0f,
TranslateAnimation.RELATIVE_TO_SELF, 0.2f, TranslateAnimation.RELATIVE_TO_SELF,
0f);
anim.addAnimation(translateAnimation);
anim.setInterpolator(new OvershootInterpolator());
view.startAnimation(anim);
} else {
view.animate().cancel();
view.animate().alpha(0f).withEndAction(() -> view.setVisibility(View.INVISIBLE));
view.animate().setDuration(400).alpha(0f);
}
}
@@ -161,35 +192,59 @@ public class ScreenDecorations extends SystemUI implements Tunable {
return;
}
if (mAssistHintBlocked && visible) {
if (VERBOSE) {
Log.v(TAG, "Assist hint blocked, cannot make it visible");
}
return;
}
if (mAssistHintVisible != visible) {
mAssistHintVisible = visible;
View assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
View assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
View assistHintBottomLeft = mBottomOverlay.findViewById(R.id.assist_hint_left);
View assistHintBottomRight = mBottomOverlay.findViewById(R.id.assist_hint_right);
CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
R.id.assist_hint_left);
CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
R.id.assist_hint_right);
switch (mRotation) {
case RotationUtils.ROTATION_NONE:
fade(assistHintBottomLeft, mAssistHintVisible);
fade(assistHintBottomRight, mAssistHintVisible);
fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
break;
case RotationUtils.ROTATION_LANDSCAPE:
fade(assistHintTopRight, mAssistHintVisible);
fade(assistHintBottomRight, mAssistHintVisible);
fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
break;
case RotationUtils.ROTATION_SEASCAPE:
fade(assistHintTopLeft, mAssistHintVisible);
fade(assistHintBottomLeft, mAssistHintVisible);
fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
break;
case RotationUtils.ROTATION_UPSIDE_DOWN:
fade(assistHintTopLeft, mAssistHintVisible);
fade(assistHintTopRight, mAssistHintVisible);
fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
break;
}
}
}
/**
* Prevents the assist hint from becoming visible even if `mAssistHintVisible` is true.
*/
public void setAssistHintBlocked(boolean blocked) {
if (!mHandler.getLooper().isCurrentThread()) {
mHandler.post(() -> setAssistHintBlocked(blocked));
return;
}
mAssistHintBlocked = blocked;
if (mAssistHintVisible && mAssistHintBlocked) {
setAssistHintVisible(false);
}
}
@VisibleForTesting
Handler startHandlerThread() {
HandlerThread thread = new HandlerThread("ScreenDecorations");
@@ -253,12 +308,12 @@ public class ScreenDecorations extends SystemUI implements Tunable {
.inflate(R.layout.rounded_corners, null);
mCutoutTop = new DisplayCutoutView(mContext, true,
this::updateWindowVisibilities, this);
((ViewGroup)mOverlay).addView(mCutoutTop);
((ViewGroup) mOverlay).addView(mCutoutTop);
mBottomOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
mCutoutBottom = new DisplayCutoutView(mContext, false,
this::updateWindowVisibilities, this);
((ViewGroup)mBottomOverlay).addView(mCutoutBottom);
((ViewGroup) mBottomOverlay).addView(mCutoutBottom);
mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mOverlay.setAlpha(0);
@@ -416,7 +471,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
} else if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
updateView(topLeft, Gravity.TOP | Gravity.LEFT, 0);
updateView(topRight, Gravity.BOTTOM | Gravity.LEFT, 270);
updateView(bottomLeft, Gravity.TOP | Gravity.RIGHT, 90);;
updateView(bottomLeft, Gravity.TOP | Gravity.RIGHT, 90);
updateView(bottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
} else if (mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
updateView(topLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
@@ -477,7 +532,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
}
private void updateView(View v, int gravity, int rotation) {
((FrameLayout.LayoutParams)v.getLayoutParams()).gravity = gravity;
((FrameLayout.LayoutParams) v.getLayoutParams()).gravity = gravity;
v.setRotation(rotation);
}
@@ -613,6 +668,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
setSize(mOverlay.findViewById(R.id.right), sizeTop);
setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
setSize(mOverlay.findViewById(R.id.assist_hint_left), sizeTop * 2);
setSize(mOverlay.findViewById(R.id.assist_hint_right), sizeTop * 2);
setSize(mBottomOverlay.findViewById(R.id.assist_hint_left), sizeBottom * 2);
setSize(mBottomOverlay.findViewById(R.id.assist_hint_right), sizeBottom * 2);
}
});
}
@@ -624,6 +683,27 @@ public class ScreenDecorations extends SystemUI implements Tunable {
view.setLayoutParams(params);
}
@Override
public void onDarkIntensity(float darkIntensity) {
if (mOverlay != null) {
CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
assistHintTopLeft.updateDarkness(darkIntensity);
assistHintTopRight.updateDarkness(darkIntensity);
}
if (mBottomOverlay != null) {
CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
R.id.assist_hint_left);
CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
R.id.assist_hint_right);
assistHintBottomLeft.updateDarkness(darkIntensity);
assistHintBottomRight.updateDarkness(darkIntensity);
}
}
@VisibleForTesting
static class TunablePaddingTagListener implements FragmentListener {

View File

@@ -86,6 +86,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.fragments.FragmentHostManager;
@@ -170,6 +171,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
public int mDisplayId;
private boolean mIsOnDefaultDisplay;
public boolean mHomeBlockedThisTouch;
private ScreenDecorations mScreenDecorations;
private Handler mHandler = Dependency.get(Dependency.MAIN_HANDLER);
@@ -348,12 +350,17 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
}
setDisabled2Flags(mDisabledFlags2);
mScreenDecorations = SysUiServiceProvider.getComponent(getContext(),
ScreenDecorations.class);
getBarTransitions().addDarkIntensityListener(mScreenDecorations);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mNavigationBarView != null) {
mNavigationBarView.getBarTransitions().removeDarkIntensityListener(mScreenDecorations);
mNavigationBarView.getBarTransitions().destroy();
mNavigationBarView.getLightTransitionsController().destroy(getContext());
}
@@ -1020,7 +1027,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
getBarTransitions().transitionTo(barMode, animate);
}
private BarTransitions getBarTransitions() {
public NavigationBarTransitions getBarTransitions() {
return mNavigationBarView.getBarTransitions();
}

View File

@@ -36,9 +36,23 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.List;
public final class NavigationBarTransitions extends BarTransitions implements
LightBarTransitionsController.DarkIntensityApplier {
/**
* Notified when the color of nav bar elements changes.
*/
public interface DarkIntensityListener {
/**
* Called when the color of nav bar elements changes.
* @param darkIntensity 0 is the lightest color, 1 is the darkest.
*/
void onDarkIntensity(float darkIntensity);
}
private final NavigationBarView mView;
private final IStatusBarService mBarService;
private final LightBarTransitionsController mLightTransitionsController;
@@ -49,6 +63,7 @@ public final class NavigationBarTransitions extends BarTransitions implements
private boolean mAutoDim;
private View mNavButtons;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private List<DarkIntensityListener> mDarkIntensityListeners;
private final Handler mHandler = Handler.getMain();
private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
@@ -69,6 +84,7 @@ public final class NavigationBarTransitions extends BarTransitions implements
mLightTransitionsController = new LightBarTransitionsController(view.getContext(), this);
mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
.getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
mDarkIntensityListeners = new ArrayList();
IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
try {
@@ -168,12 +184,16 @@ public final class NavigationBarTransitions extends BarTransitions implements
applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
}
@Override
public void applyDarkIntensity(float darkIntensity) {
SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
}
mView.getRotationButtonController().setDarkIntensity(darkIntensity);
for (DarkIntensityListener listener : mDarkIntensityListeners) {
listener.onDarkIntensity(darkIntensity);
}
if (mAutoDim) {
applyLightsOut(false, true);
}
@@ -190,4 +210,18 @@ public final class NavigationBarTransitions extends BarTransitions implements
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
}
/**
* Register {@code listener} to be notified when the color of nav bar elements changes.
*/
public void addDarkIntensityListener(DarkIntensityListener listener) {
mDarkIntensityListeners.add(listener);
}
/**
* Remove {@code listener} from being notified when the color of nav bar elements changes.
*/
public void removeDarkIntensityListener(DarkIntensityListener listener) {
mDarkIntensityListeners.remove(listener);
}
}

View File

@@ -299,7 +299,7 @@ public class NavigationBarView extends FrameLayout implements
return mTintController;
}
public BarTransitions getBarTransitions() {
public NavigationBarTransitions getBarTransitions() {
return mBarTransitions;
}

View File

@@ -268,7 +268,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
when(view.getRecentsButton()).thenReturn(mock(ButtonDispatcher.class));
when(view.getAccessibilityButton()).thenReturn(mock(ButtonDispatcher.class));
when(view.getRotateSuggestionButton()).thenReturn(mock(RotationContextButton.class));
when(view.getBarTransitions()).thenReturn(mock(BarTransitions.class));
when(view.getBarTransitions()).thenReturn(mock(NavigationBarTransitions.class));
when(view.getLightTransitionsController()).thenReturn(
mock(LightBarTransitionsController.class));
when(view.getRotationButtonController()).thenReturn(