2021-06-01 16:54:07 -07:00
|
|
|
/*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
|
|
|
|
package com.android.launcher3.taskbar;
|
|
|
|
|
|
|
|
|
|
import android.animation.Animator;
|
Stash taskbar when IME is present, including during gestures
- SysUI removes SYSUI_STATE_IME_SHOWING when starting a gesture from an app, but because unstashing has implications on the gesture transition (e.g. clips the bottom of the app), we defer handling the ime hiding until the gesture settles. Repurposed the flow that swaps the taskbar background during the gesture to support this case as well.
- Delay the unstash when IME is closing, to align with the end of the IME exit transition
- Remove TaskbarViewController.ALPHA_INDEX_IME now that we stash when IME is opening, since stashing already hides the taskbar icons
- Also support passing a starting progress to the stashed handle reveal animation, to allow it to be reversed when cancelled. For example, when returning to an app that has IME showing, we first start unstashing because we're in an app, but then we get the signal that IME is attached so we stash again almost immediately (within a frame or two).
Test: In both 3 button and fully gestural, open a keyboard in an app, ensure taskbar gets out of the way and then reappears at the end when the keyboard is dismissed
Bug: 202511986
Change-Id: I93c298a98ba369ea6310466ff3f802231c582687
2021-11-16 17:38:36 -08:00
|
|
|
import android.animation.AnimatorListenerAdapter;
|
|
|
|
|
import android.animation.ValueAnimator;
|
2021-08-17 16:07:22 -07:00
|
|
|
import android.content.SharedPreferences;
|
2021-06-01 16:54:07 -07:00
|
|
|
import android.content.res.Resources;
|
|
|
|
|
import android.graphics.Outline;
|
|
|
|
|
import android.graphics.Rect;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.ViewOutlineProvider;
|
|
|
|
|
|
2022-06-08 14:01:02 -07:00
|
|
|
import com.android.launcher3.DeviceProfile;
|
2021-06-01 16:54:07 -07:00
|
|
|
import com.android.launcher3.R;
|
2021-08-17 16:07:22 -07:00
|
|
|
import com.android.launcher3.Utilities;
|
2021-06-01 16:54:07 -07:00
|
|
|
import com.android.launcher3.anim.RevealOutlineAnimation;
|
|
|
|
|
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
|
2022-11-07 13:50:49 -08:00
|
|
|
import com.android.launcher3.util.DisplayController;
|
2021-08-17 16:07:22 -07:00
|
|
|
import com.android.launcher3.util.Executors;
|
2022-09-13 14:40:48 -07:00
|
|
|
import com.android.launcher3.util.MultiPropertyFactory;
|
2021-09-28 15:09:25 -07:00
|
|
|
import com.android.launcher3.util.MultiValueAlpha;
|
2021-06-01 16:54:07 -07:00
|
|
|
import com.android.quickstep.AnimatedFloat;
|
2021-08-17 16:07:22 -07:00
|
|
|
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
|
2021-06-01 16:54:07 -07:00
|
|
|
|
2021-12-15 13:09:39 -08:00
|
|
|
import java.io.PrintWriter;
|
|
|
|
|
|
2021-06-01 16:54:07 -07:00
|
|
|
/**
|
|
|
|
|
* Handles properties/data collection, then passes the results to our stashed handle View to render.
|
|
|
|
|
*/
|
2021-12-15 13:09:39 -08:00
|
|
|
public class StashedHandleViewController implements TaskbarControllers.LoggableTaskbarController {
|
2021-06-01 16:54:07 -07:00
|
|
|
|
2021-09-28 15:09:25 -07:00
|
|
|
public static final int ALPHA_INDEX_STASHED = 0;
|
|
|
|
|
public static final int ALPHA_INDEX_HOME_DISABLED = 1;
|
2022-04-04 14:58:30 -07:00
|
|
|
public static final int ALPHA_INDEX_ASSISTANT_INVOKED = 2;
|
|
|
|
|
private static final int NUM_ALPHA_CHANNELS = 3;
|
2021-09-28 15:09:25 -07:00
|
|
|
|
2021-08-17 16:07:22 -07:00
|
|
|
/**
|
|
|
|
|
* The SharedPreferences key for whether the stashed handle region is dark.
|
|
|
|
|
*/
|
|
|
|
|
private static final String SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY =
|
|
|
|
|
"stashed_handle_region_is_dark";
|
|
|
|
|
|
2021-06-01 16:54:07 -07:00
|
|
|
private final TaskbarActivityContext mActivity;
|
2021-08-17 16:07:22 -07:00
|
|
|
private final SharedPreferences mPrefs;
|
|
|
|
|
private final StashedHandleView mStashedHandleView;
|
2022-06-08 14:01:02 -07:00
|
|
|
private int mStashedHandleWidth;
|
2021-06-01 16:54:07 -07:00
|
|
|
private final int mStashedHandleHeight;
|
2022-06-08 14:01:02 -07:00
|
|
|
private RegionSamplingHelper mRegionSamplingHelper;
|
2021-09-28 15:09:25 -07:00
|
|
|
private final MultiValueAlpha mTaskbarStashedHandleAlpha;
|
2021-07-16 12:15:35 -10:00
|
|
|
private final AnimatedFloat mTaskbarStashedHandleHintScale = new AnimatedFloat(
|
|
|
|
|
this::updateStashedHandleHintScale);
|
2021-06-01 16:54:07 -07:00
|
|
|
|
|
|
|
|
// Initialized in init.
|
|
|
|
|
private TaskbarControllers mControllers;
|
2022-11-07 13:50:49 -08:00
|
|
|
private int mTaskbarSize;
|
2021-06-01 16:54:07 -07:00
|
|
|
|
|
|
|
|
// The bounds we want to clip to in the settled state when showing the stashed handle.
|
|
|
|
|
private final Rect mStashedHandleBounds = new Rect();
|
|
|
|
|
private float mStashedHandleRadius;
|
|
|
|
|
|
Stash taskbar when IME is present, including during gestures
- SysUI removes SYSUI_STATE_IME_SHOWING when starting a gesture from an app, but because unstashing has implications on the gesture transition (e.g. clips the bottom of the app), we defer handling the ime hiding until the gesture settles. Repurposed the flow that swaps the taskbar background during the gesture to support this case as well.
- Delay the unstash when IME is closing, to align with the end of the IME exit transition
- Remove TaskbarViewController.ALPHA_INDEX_IME now that we stash when IME is opening, since stashing already hides the taskbar icons
- Also support passing a starting progress to the stashed handle reveal animation, to allow it to be reversed when cancelled. For example, when returning to an app that has IME showing, we first start unstashing because we're in an app, but then we get the signal that IME is attached so we stash again almost immediately (within a frame or two).
Test: In both 3 button and fully gestural, open a keyboard in an app, ensure taskbar gets out of the way and then reappears at the end when the keyboard is dismissed
Bug: 202511986
Change-Id: I93c298a98ba369ea6310466ff3f802231c582687
2021-11-16 17:38:36 -08:00
|
|
|
// When the reveal animation is cancelled, we can assume it's about to create a new animation,
|
|
|
|
|
// which should start off at the same point the cancelled one left off.
|
|
|
|
|
private float mStartProgressForNextRevealAnim;
|
|
|
|
|
private boolean mWasLastRevealAnimReversed;
|
2021-06-01 16:54:07 -07:00
|
|
|
|
2021-08-17 16:07:22 -07:00
|
|
|
public StashedHandleViewController(TaskbarActivityContext activity,
|
|
|
|
|
StashedHandleView stashedHandleView) {
|
2021-06-01 16:54:07 -07:00
|
|
|
mActivity = activity;
|
2021-08-17 16:07:22 -07:00
|
|
|
mPrefs = Utilities.getPrefs(mActivity);
|
2021-06-01 16:54:07 -07:00
|
|
|
mStashedHandleView = stashedHandleView;
|
2021-09-28 15:09:25 -07:00
|
|
|
mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, NUM_ALPHA_CHANNELS);
|
|
|
|
|
mTaskbarStashedHandleAlpha.setUpdateVisibility(true);
|
2021-08-17 16:07:22 -07:00
|
|
|
mStashedHandleView.updateHandleColor(
|
2021-09-29 16:16:43 -07:00
|
|
|
mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false),
|
|
|
|
|
false /* animate */);
|
2021-06-01 16:54:07 -07:00
|
|
|
final Resources resources = mActivity.getResources();
|
|
|
|
|
mStashedHandleHeight = resources.getDimensionPixelSize(
|
|
|
|
|
R.dimen.taskbar_stashed_handle_height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void init(TaskbarControllers controllers) {
|
|
|
|
|
mControllers = controllers;
|
2022-06-08 14:01:02 -07:00
|
|
|
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
|
|
|
|
|
Resources resources = mActivity.getResources();
|
2022-08-05 10:43:29 -07:00
|
|
|
if (isPhoneGestureNavMode(mActivity.getDeviceProfile())) {
|
2022-11-07 13:50:49 -08:00
|
|
|
mTaskbarSize = resources.getDimensionPixelSize(R.dimen.taskbar_size);
|
2022-06-08 14:01:02 -07:00
|
|
|
mStashedHandleWidth =
|
|
|
|
|
resources.getDimensionPixelSize(R.dimen.taskbar_stashed_small_screen);
|
|
|
|
|
} else {
|
2022-11-07 13:50:49 -08:00
|
|
|
mTaskbarSize = deviceProfile.taskbarSize;
|
2022-08-11 17:33:35 -07:00
|
|
|
mStashedHandleWidth = resources
|
|
|
|
|
.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
|
2022-06-08 14:01:02 -07:00
|
|
|
}
|
2022-11-07 13:50:49 -08:00
|
|
|
int taskbarBottomMargin = DisplayController.isTransientTaskbar(mActivity)
|
|
|
|
|
? resources.getDimensionPixelSize(R.dimen.transient_taskbar_margin)
|
|
|
|
|
: 0;
|
|
|
|
|
mStashedHandleView.getLayoutParams().height = mTaskbarSize + taskbarBottomMargin;
|
2022-06-08 14:01:02 -07:00
|
|
|
|
2022-09-13 14:40:48 -07:00
|
|
|
mTaskbarStashedHandleAlpha.get(ALPHA_INDEX_STASHED).setValue(
|
2022-08-05 10:43:29 -07:00
|
|
|
isPhoneGestureNavMode(deviceProfile) ? 1 : 0);
|
2021-07-16 12:15:35 -10:00
|
|
|
mTaskbarStashedHandleHintScale.updateValue(1f);
|
2021-06-01 16:54:07 -07:00
|
|
|
|
|
|
|
|
final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
|
|
|
|
|
mStashedHandleView.setOutlineProvider(new ViewOutlineProvider() {
|
|
|
|
|
@Override
|
|
|
|
|
public void getOutline(View view, Outline outline) {
|
|
|
|
|
final int stashedCenterX = view.getWidth() / 2;
|
|
|
|
|
final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
|
|
|
|
|
mStashedHandleBounds.set(
|
|
|
|
|
stashedCenterX - mStashedHandleWidth / 2,
|
|
|
|
|
stashedCenterY - mStashedHandleHeight / 2,
|
|
|
|
|
stashedCenterX + mStashedHandleWidth / 2,
|
|
|
|
|
stashedCenterY + mStashedHandleHeight / 2);
|
2021-09-29 15:41:08 -07:00
|
|
|
mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
|
2021-06-01 16:54:07 -07:00
|
|
|
mStashedHandleRadius = view.getHeight() / 2f;
|
|
|
|
|
outline.setRoundRect(mStashedHandleBounds, mStashedHandleRadius);
|
|
|
|
|
}
|
|
|
|
|
});
|
2021-07-16 12:15:35 -10:00
|
|
|
|
|
|
|
|
mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> {
|
|
|
|
|
final int stashedCenterX = view.getWidth() / 2;
|
|
|
|
|
final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
|
|
|
|
|
|
|
|
|
|
view.setPivotX(stashedCenterX);
|
|
|
|
|
view.setPivotY(stashedCenterY);
|
|
|
|
|
});
|
2022-06-08 14:01:02 -07:00
|
|
|
initRegionSampler();
|
2022-08-05 10:43:29 -07:00
|
|
|
if (isPhoneGestureNavMode(deviceProfile)) {
|
2022-06-08 14:01:02 -07:00
|
|
|
onIsStashedChanged(true);
|
|
|
|
|
}
|
2021-06-01 16:54:07 -07:00
|
|
|
}
|
|
|
|
|
|
2022-06-08 14:01:02 -07:00
|
|
|
private void initRegionSampler() {
|
|
|
|
|
mRegionSamplingHelper = new RegionSamplingHelper(mStashedHandleView,
|
|
|
|
|
new RegionSamplingHelper.SamplingCallback() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onRegionDarknessChanged(boolean isRegionDark) {
|
|
|
|
|
mStashedHandleView.updateHandleColor(isRegionDark, true /* animate */);
|
|
|
|
|
mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY,
|
|
|
|
|
isRegionDark).apply();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Rect getSampledRegion(View sampledView) {
|
|
|
|
|
return mStashedHandleView.getSampledRegion();
|
|
|
|
|
}
|
|
|
|
|
}, Executors.UI_HELPER_EXECUTOR);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-17 16:07:22 -07:00
|
|
|
public void onDestroy() {
|
|
|
|
|
mRegionSamplingHelper.stopAndDestroy();
|
2022-06-08 14:01:02 -07:00
|
|
|
mRegionSamplingHelper = null;
|
2021-08-17 16:07:22 -07:00
|
|
|
}
|
2022-08-05 10:43:29 -07:00
|
|
|
|
|
|
|
|
private boolean isPhoneGestureNavMode(DeviceProfile deviceProfile) {
|
|
|
|
|
return TaskbarManager.isPhoneMode(deviceProfile) && !mActivity.isThreeButtonNav();
|
|
|
|
|
}
|
2021-08-17 16:07:22 -07:00
|
|
|
|
2022-09-13 14:40:48 -07:00
|
|
|
public MultiPropertyFactory<View> getStashedHandleAlpha() {
|
2021-06-01 16:54:07 -07:00
|
|
|
return mTaskbarStashedHandleAlpha;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 12:15:35 -10:00
|
|
|
public AnimatedFloat getStashedHandleHintScale() {
|
|
|
|
|
return mTaskbarStashedHandleHintScale;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-01 16:54:07 -07:00
|
|
|
/**
|
|
|
|
|
* Creates and returns a {@link RevealOutlineAnimation} Animator that updates the stashed handle
|
|
|
|
|
* shape and size. When stashed, the shape is a thin rounded pill. When unstashed, the shape
|
|
|
|
|
* morphs into the size of where the taskbar icons will be.
|
|
|
|
|
*/
|
Stash taskbar when IME is present, including during gestures
- SysUI removes SYSUI_STATE_IME_SHOWING when starting a gesture from an app, but because unstashing has implications on the gesture transition (e.g. clips the bottom of the app), we defer handling the ime hiding until the gesture settles. Repurposed the flow that swaps the taskbar background during the gesture to support this case as well.
- Delay the unstash when IME is closing, to align with the end of the IME exit transition
- Remove TaskbarViewController.ALPHA_INDEX_IME now that we stash when IME is opening, since stashing already hides the taskbar icons
- Also support passing a starting progress to the stashed handle reveal animation, to allow it to be reversed when cancelled. For example, when returning to an app that has IME showing, we first start unstashing because we're in an app, but then we get the signal that IME is attached so we stash again almost immediately (within a frame or two).
Test: In both 3 button and fully gestural, open a keyboard in an app, ensure taskbar gets out of the way and then reappears at the end when the keyboard is dismissed
Bug: 202511986
Change-Id: I93c298a98ba369ea6310466ff3f802231c582687
2021-11-16 17:38:36 -08:00
|
|
|
public Animator createRevealAnimToIsStashed(boolean isStashed) {
|
2022-11-07 13:50:49 -08:00
|
|
|
Rect visualBounds = new Rect(mControllers.taskbarViewController.getIconLayoutBounds());
|
|
|
|
|
|
|
|
|
|
if (DisplayController.isTransientTaskbar(mActivity)) {
|
|
|
|
|
// Account for the full visual height of the transient taskbar.
|
|
|
|
|
int heightDiff = (mTaskbarSize - visualBounds.height()) / 2;
|
|
|
|
|
visualBounds.top -= heightDiff;
|
|
|
|
|
visualBounds.bottom += heightDiff;
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-01 16:54:07 -07:00
|
|
|
final RevealOutlineAnimation handleRevealProvider = new RoundedRectRevealOutlineProvider(
|
2022-11-07 13:50:49 -08:00
|
|
|
mStashedHandleRadius, mStashedHandleRadius, visualBounds, mStashedHandleBounds);
|
Stash taskbar when IME is present, including during gestures
- SysUI removes SYSUI_STATE_IME_SHOWING when starting a gesture from an app, but because unstashing has implications on the gesture transition (e.g. clips the bottom of the app), we defer handling the ime hiding until the gesture settles. Repurposed the flow that swaps the taskbar background during the gesture to support this case as well.
- Delay the unstash when IME is closing, to align with the end of the IME exit transition
- Remove TaskbarViewController.ALPHA_INDEX_IME now that we stash when IME is opening, since stashing already hides the taskbar icons
- Also support passing a starting progress to the stashed handle reveal animation, to allow it to be reversed when cancelled. For example, when returning to an app that has IME showing, we first start unstashing because we're in an app, but then we get the signal that IME is attached so we stash again almost immediately (within a frame or two).
Test: In both 3 button and fully gestural, open a keyboard in an app, ensure taskbar gets out of the way and then reappears at the end when the keyboard is dismissed
Bug: 202511986
Change-Id: I93c298a98ba369ea6310466ff3f802231c582687
2021-11-16 17:38:36 -08:00
|
|
|
|
|
|
|
|
boolean isReversed = !isStashed;
|
|
|
|
|
boolean changingDirection = mWasLastRevealAnimReversed != isReversed;
|
|
|
|
|
mWasLastRevealAnimReversed = isReversed;
|
|
|
|
|
if (changingDirection) {
|
|
|
|
|
mStartProgressForNextRevealAnim = 1f - mStartProgressForNextRevealAnim;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ValueAnimator revealAnim = handleRevealProvider.createRevealAnimator(mStashedHandleView,
|
|
|
|
|
isReversed, mStartProgressForNextRevealAnim);
|
|
|
|
|
revealAnim.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
|
mStartProgressForNextRevealAnim = ((ValueAnimator) animation).getAnimatedFraction();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return revealAnim;
|
2021-06-01 16:54:07 -07:00
|
|
|
}
|
|
|
|
|
|
2022-04-15 16:01:38 -07:00
|
|
|
/** Called when taskbar is stashed or unstashed. */
|
|
|
|
|
public void onIsStashedChanged(boolean isStashed) {
|
2021-08-17 16:07:22 -07:00
|
|
|
mRegionSamplingHelper.setWindowVisible(isStashed);
|
|
|
|
|
if (isStashed) {
|
2021-09-29 15:41:08 -07:00
|
|
|
mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
|
2021-08-17 16:07:22 -07:00
|
|
|
mRegionSamplingHelper.start(mStashedHandleView.getSampledRegion());
|
|
|
|
|
} else {
|
|
|
|
|
mRegionSamplingHelper.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-16 12:15:35 -10:00
|
|
|
protected void updateStashedHandleHintScale() {
|
|
|
|
|
mStashedHandleView.setScaleX(mTaskbarStashedHandleHintScale.value);
|
|
|
|
|
mStashedHandleView.setScaleY(mTaskbarStashedHandleHintScale.value);
|
|
|
|
|
}
|
2021-09-28 15:09:25 -07:00
|
|
|
|
2022-11-07 13:50:49 -08:00
|
|
|
/**
|
|
|
|
|
* Sets the translation of the stashed handle during the swipe up gesture.
|
|
|
|
|
*/
|
|
|
|
|
protected void setTranslationYForSwipe(float transY) {
|
|
|
|
|
mStashedHandleView.setTranslationY(transY);
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-28 15:09:25 -07:00
|
|
|
/**
|
|
|
|
|
* Should be called when the home button is disabled, so we can hide this handle as well.
|
|
|
|
|
*/
|
|
|
|
|
public void setIsHomeButtonDisabled(boolean homeDisabled) {
|
2022-09-13 14:40:48 -07:00
|
|
|
mTaskbarStashedHandleAlpha.get(ALPHA_INDEX_HOME_DISABLED).setValue(
|
2021-09-28 15:09:25 -07:00
|
|
|
homeDisabled ? 0 : 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public boolean isStashedHandleVisible() {
|
|
|
|
|
return mStashedHandleView.getVisibility() == View.VISIBLE;
|
|
|
|
|
}
|
2021-12-15 13:09:39 -08:00
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void dumpLogs(String prefix, PrintWriter pw) {
|
|
|
|
|
pw.println(prefix + "StashedHandleViewController:");
|
|
|
|
|
|
2022-06-23 11:25:10 -07:00
|
|
|
pw.println(prefix + "\tisStashedHandleVisible=" + isStashedHandleVisible());
|
|
|
|
|
pw.println(prefix + "\tmStashedHandleWidth=" + mStashedHandleWidth);
|
|
|
|
|
pw.println(prefix + "\tmStashedHandleHeight=" + mStashedHandleHeight);
|
2021-12-15 13:09:39 -08:00
|
|
|
mRegionSamplingHelper.dump(prefix, pw);
|
|
|
|
|
}
|
2021-06-01 16:54:07 -07:00
|
|
|
}
|