Merge "Apply theme color and fade-in transition effect at the top of One-handed mode" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a08d1cb0f1
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
<item android:color="?androidprv:attr/colorSurfaceVariant"/>
|
||||
</selector>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,14 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="60dp"
|
||||
android:viewportWidth="32"
|
||||
android:viewportHeight="60">
|
||||
<path
|
||||
android:pathData="M1.9703,30.5041C1.9703,28.295 3.7612,26.5042 5.9703,26.5042H25.5551C27.7642,26.5042 29.5551,28.295 29.5551,30.5042V54.0296C29.5551,56.2387 27.7642,58.0296 25.5551,58.0296H5.9703C3.7612,58.0296 1.9703,56.2387 1.9703,54.0296V30.5041Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillAlpha="0.16"/>
|
||||
<path
|
||||
android:pathData="M25.5254,2H6C3.7909,2 2,3.7909 2,6V54C2,56.2091 3.7909,58 6,58H25.5254C27.7346,58 29.5254,56.2091 29.5254,54V6C29.5254,3.7909 27.7346,2 25.5254,2ZM6,0C2.6863,0 0,2.6863 0,6V54C0,57.3137 2.6863,60 6,60H25.5254C28.8391,60 31.5254,57.3137 31.5254,54V6C31.5254,2.6863 28.8391,0 25.5254,0H6ZM12.2034,47.2336L12.8307,47.861L15.3178,45.3783V52.1277H16.2076V45.3783L18.6903,47.8654L19.322,47.2336L15.7627,43.6743L12.2034,47.2336ZM19.7034,55.0742H11.822V56.552H19.7034V55.0742Z"
|
||||
android:fillColor="#000000"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@@ -31,7 +31,7 @@
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:src="@drawable/one_handed_tutorial"
|
||||
android:src="@drawable/one_handed_tutorial_icon"
|
||||
android:scaleType="centerInside" />
|
||||
|
||||
<TextView
|
||||
@@ -45,7 +45,6 @@
|
||||
android:fontFamily="google-sans-medium"
|
||||
android:text="@string/one_handed_tutorial_title"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
<TextView
|
||||
@@ -54,8 +53,8 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_marginStart="46dp"
|
||||
android:layout_marginEnd="46dp"
|
||||
android:layout_marginStart="60dp"
|
||||
android:layout_marginEnd="60dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:fontFamily="roboto-regular"
|
||||
android:text="@string/one_handed_tutorial_description"
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceSession;
|
||||
import android.window.DisplayAreaAppearedInfo;
|
||||
@@ -30,7 +29,6 @@ import android.window.DisplayAreaOrganizer;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.wm.shell.R;
|
||||
@@ -48,14 +46,17 @@ import java.util.concurrent.Executor;
|
||||
public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
|
||||
implements OneHandedTransitionCallback {
|
||||
private static final String TAG = "OneHandedBackgroundPanelOrganizer";
|
||||
private static final int THEME_COLOR_OFFSET = 10;
|
||||
|
||||
private final Context mContext;
|
||||
private final Object mLock = new Object();
|
||||
private final SurfaceSession mSurfaceSession = new SurfaceSession();
|
||||
private final float[] mDefaultColor;
|
||||
private final Executor mMainExecutor;
|
||||
private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
|
||||
mSurfaceControlTransactionFactory;
|
||||
|
||||
private float[] mDefaultColor;
|
||||
|
||||
/**
|
||||
* The background to distinguish the boundary of translated windows and empty region when
|
||||
* one handed mode triggered.
|
||||
@@ -88,15 +89,14 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
|
||||
public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
|
||||
Executor executor) {
|
||||
super(executor);
|
||||
mContext = context;
|
||||
// Ensure the mBkgBounds is portrait, due to OHM only support on portrait
|
||||
if (displayLayout.height() > displayLayout.width()) {
|
||||
mBkgBounds = new Rect(0, 0, displayLayout.width(), displayLayout.height());
|
||||
} else {
|
||||
mBkgBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
|
||||
}
|
||||
final int defaultColor = ContextCompat.getColor(context, R.color.GM2_grey_800);
|
||||
mDefaultColor = new float[]{Color.red(defaultColor) / 255.0f,
|
||||
Color.green(defaultColor) / 255.0f, Color.blue(defaultColor) / 255.0f};
|
||||
updateThemeColors();
|
||||
mMainExecutor = executor;
|
||||
mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
|
||||
}
|
||||
@@ -170,7 +170,6 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
|
||||
}
|
||||
|
||||
if (getBackgroundSurface() == null) {
|
||||
Log.w(TAG, "mBackgroundSurface is null !");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -201,6 +200,30 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* onConfigurationChanged events for updating tutorial text.
|
||||
*/
|
||||
public void onConfigurationChanged() {
|
||||
synchronized (mLock) {
|
||||
if (mBackgroundSurface == null) {
|
||||
getBackgroundSurface();
|
||||
} else {
|
||||
removeBackgroundPanelLayer();
|
||||
}
|
||||
updateThemeColors();
|
||||
showBackgroundPanelLayer();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThemeColors() {
|
||||
synchronized (mLock) {
|
||||
final int themeColor = mContext.getColor(R.color.one_handed_tutorial_background_color);
|
||||
mDefaultColor = new float[]{(Color.red(themeColor) - THEME_COLOR_OFFSET) / 255.0f,
|
||||
(Color.green(themeColor) - THEME_COLOR_OFFSET) / 255.0f,
|
||||
(Color.blue(themeColor) - THEME_COLOR_OFFSET) / 255.0f};
|
||||
}
|
||||
}
|
||||
|
||||
void dump(@NonNull PrintWriter pw) {
|
||||
final String innerPrefix = " ";
|
||||
pw.println(TAG);
|
||||
|
||||
@@ -658,12 +658,13 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
}
|
||||
|
||||
private void onConfigChanged(Configuration newConfig) {
|
||||
if (mTutorialHandler == null) {
|
||||
if (mTutorialHandler == null || mBackgroundPanelOrganizer == null) {
|
||||
return;
|
||||
}
|
||||
if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
return;
|
||||
}
|
||||
mBackgroundPanelOrganizer.onConfigurationChanged();
|
||||
mTutorialHandler.onConfigurationChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,11 @@ import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_EXITING;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
|
||||
|
||||
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.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemProperties;
|
||||
@@ -35,9 +38,13 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.view.ContextThemeWrapper;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.wm.shell.R;
|
||||
@@ -53,11 +60,14 @@ import java.io.PrintWriter;
|
||||
public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
OneHandedState.OnStateChangedListener {
|
||||
private static final String TAG = "OneHandedTutorialHandler";
|
||||
private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
|
||||
"persist.debug.one_handed_offset_percentage";
|
||||
private static final String OFFSET_PERCENTAGE = "persist.debug.one_handed_offset_percentage";
|
||||
private static final String TRANSLATE_ANIMATION_DURATION =
|
||||
"persist.debug.one_handed_translate_animation_duration";
|
||||
private static final float START_TRANSITION_FRACTION = 0.7f;
|
||||
|
||||
private final float mTutorialHeightRatio;
|
||||
private final WindowManager mWindowManager;
|
||||
private final OneHandedAnimationCallback mAnimationCallback;
|
||||
|
||||
private @OneHandedState.State int mCurrentState;
|
||||
private int mTutorialAreaHeight;
|
||||
@@ -67,7 +77,9 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
private @Nullable View mTutorialView;
|
||||
private @Nullable ViewGroup mTargetViewContainer;
|
||||
|
||||
private final OneHandedAnimationCallback mAnimationCallback;
|
||||
private float mAlphaTransitionStart;
|
||||
private ValueAnimator mAlphaAnimator;
|
||||
private int mAlphaAnimationDurationMs;
|
||||
|
||||
public OneHandedTutorialHandler(Context context, WindowManager windowManager) {
|
||||
mContext = context;
|
||||
@@ -75,15 +87,35 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
final float offsetPercentageConfig = context.getResources().getFraction(
|
||||
R.fraction.config_one_handed_offset, 1, 1);
|
||||
final int sysPropPercentageConfig = SystemProperties.getInt(
|
||||
ONE_HANDED_MODE_OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
|
||||
OFFSET_PERCENTAGE, Math.round(offsetPercentageConfig * 100.0f));
|
||||
mTutorialHeightRatio = sysPropPercentageConfig / 100.0f;
|
||||
final int animationDuration = context.getResources().getInteger(
|
||||
R.integer.config_one_handed_translate_animation_duration);
|
||||
mAlphaAnimationDurationMs = SystemProperties.getInt(TRANSLATE_ANIMATION_DURATION,
|
||||
animationDuration);
|
||||
mAnimationCallback = new OneHandedAnimationCallback() {
|
||||
@Override
|
||||
public void onOneHandedAnimationCancel(
|
||||
OneHandedAnimationController.OneHandedTransitionAnimator animator) {
|
||||
if (mAlphaAnimator != null) {
|
||||
mAlphaAnimator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationUpdate(float xPos, float yPos) {
|
||||
if (!isAttached()) {
|
||||
return;
|
||||
}
|
||||
mTargetViewContainer.setTranslationY(yPos - mTutorialAreaHeight);
|
||||
if (yPos < mAlphaTransitionStart) {
|
||||
checkTransitionEnd();
|
||||
return;
|
||||
}
|
||||
if (mAlphaAnimator == null || mAlphaAnimator.isStarted()
|
||||
|| mAlphaAnimator.isRunning()) {
|
||||
return;
|
||||
}
|
||||
mAlphaAnimator.start();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -94,12 +126,16 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
switch (newState) {
|
||||
case STATE_ENTERING:
|
||||
createViewAndAttachToWindow(mContext);
|
||||
updateThemeColor();
|
||||
setupAlphaTransition(true /* isEntering */);
|
||||
break;
|
||||
case STATE_ACTIVE:
|
||||
case STATE_EXITING:
|
||||
// no - op
|
||||
checkTransitionEnd();
|
||||
setupAlphaTransition(false /* isEntering */);
|
||||
break;
|
||||
case STATE_EXITING:
|
||||
case STATE_NONE:
|
||||
checkTransitionEnd();
|
||||
removeTutorialFromWindowManager();
|
||||
break;
|
||||
default:
|
||||
@@ -119,6 +155,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
mDisplayBounds = new Rect(0, 0, displayLayout.height(), displayLayout.width());
|
||||
}
|
||||
mTutorialAreaHeight = Math.round(mDisplayBounds.height() * mTutorialHeightRatio);
|
||||
mAlphaTransitionStart = mTutorialAreaHeight * START_TRANSITION_FRACTION;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -129,6 +166,7 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
mTutorialView = LayoutInflater.from(context).inflate(R.layout.one_handed_tutorial, null);
|
||||
mTargetViewContainer = new FrameLayout(context);
|
||||
mTargetViewContainer.setClipChildren(false);
|
||||
mTargetViewContainer.setAlpha(mCurrentState == STATE_ACTIVE ? 1.0f : 0.0f);
|
||||
mTargetViewContainer.addView(mTutorialView);
|
||||
mTargetViewContainer.setLayerType(LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
@@ -192,6 +230,52 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
removeTutorialFromWindowManager();
|
||||
if (mCurrentState == STATE_ENTERING || mCurrentState == STATE_ACTIVE) {
|
||||
createViewAndAttachToWindow(mContext);
|
||||
updateThemeColor();
|
||||
checkTransitionEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThemeColor() {
|
||||
if (mTutorialView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Context themedContext = new ContextThemeWrapper(mTutorialView.getContext(),
|
||||
com.android.internal.R.style.Theme_DeviceDefault_DayNight);
|
||||
final int textColorPrimary;
|
||||
final int themedTextColorSecondary;
|
||||
TypedArray ta = themedContext.obtainStyledAttributes(new int[]{
|
||||
com.android.internal.R.attr.textColorPrimary,
|
||||
com.android.internal.R.attr.textColorSecondary});
|
||||
textColorPrimary = ta.getColor(0, 0);
|
||||
themedTextColorSecondary = ta.getColor(1, 0);
|
||||
ta.recycle();
|
||||
|
||||
final ImageView iconView = mTutorialView.findViewById(R.id.one_handed_tutorial_image);
|
||||
iconView.setImageTintList(ColorStateList.valueOf(textColorPrimary));
|
||||
|
||||
final TextView tutorialTitle = mTutorialView.findViewById(R.id.one_handed_tutorial_title);
|
||||
final TextView tutorialDesc = mTutorialView.findViewById(
|
||||
R.id.one_handed_tutorial_description);
|
||||
tutorialTitle.setTextColor(textColorPrimary);
|
||||
tutorialDesc.setTextColor(themedTextColorSecondary);
|
||||
}
|
||||
|
||||
private void setupAlphaTransition(boolean isEntering) {
|
||||
final float start = isEntering ? 0.0f : 1.0f;
|
||||
final float end = isEntering ? 1.0f : 0.0f;
|
||||
mAlphaAnimator = ValueAnimator.ofFloat(start, end);
|
||||
mAlphaAnimator.setInterpolator(new LinearInterpolator());
|
||||
mAlphaAnimator.setDuration(mAlphaAnimationDurationMs);
|
||||
mAlphaAnimator.addUpdateListener(
|
||||
animator -> mTargetViewContainer.setAlpha((float) animator.getAnimatedValue()));
|
||||
}
|
||||
|
||||
private void checkTransitionEnd() {
|
||||
if (mAlphaAnimator != null && mAlphaAnimator.isRunning()) {
|
||||
mAlphaAnimator.end();
|
||||
mAlphaAnimator.removeAllUpdateListeners();
|
||||
mAlphaAnimator = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,5 +290,9 @@ public class OneHandedTutorialHandler implements OneHandedTransitionCallback,
|
||||
pw.println(mDisplayBounds);
|
||||
pw.print(innerPrefix + "mTutorialAreaHeight=");
|
||||
pw.println(mTutorialAreaHeight);
|
||||
pw.print(innerPrefix + "mAlphaTransitionStart=");
|
||||
pw.println(mAlphaTransitionStart);
|
||||
pw.print(innerPrefix + "mAlphaAnimationDurationMs=");
|
||||
pw.println(mAlphaAnimationDurationMs);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user