Merge "Initial commit of taskbar stashing" into sc-v2-dev
This commit is contained in:
commit
0ac023196d
|
@ -15,6 +15,7 @@
|
|||
-->
|
||||
<com.android.launcher3.taskbar.TaskbarDragLayer
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/taskbar_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -39,6 +40,7 @@
|
|||
android:id="@+id/start_nav_buttons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
|
||||
android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
|
||||
android:gravity="center_vertical"
|
||||
|
@ -54,4 +56,14 @@
|
|||
android:layout_gravity="end"/>
|
||||
</FrameLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/stashed_handle"
|
||||
tools:comment1="The actual size and shape will be set as a ViewOutlineProvider at runtime"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
tools:comment2="TODO: Tint dynamically"
|
||||
android:background="?android:attr/textColorPrimary"
|
||||
android:clipToOutline="true"
|
||||
android:layout_gravity="bottom"/>
|
||||
|
||||
</com.android.launcher3.taskbar.TaskbarDragLayer>
|
|
@ -153,4 +153,7 @@
|
|||
<dimen name="taskbar_folder_margin">16dp</dimen>
|
||||
<dimen name="taskbar_nav_buttons_spacing">16dp</dimen>
|
||||
<dimen name="taskbar_nav_buttons_size">48dp</dimen>
|
||||
<dimen name="taskbar_stashed_size">24dp</dimen>
|
||||
<dimen name="taskbar_stashed_handle_width">220dp</dimen>
|
||||
<dimen name="taskbar_stashed_handle_height">6dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -50,21 +50,23 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
|||
private final TaskbarHotseatController mHotseatController;
|
||||
|
||||
private final TaskbarActivityContext mContext;
|
||||
final TaskbarDragLayer mTaskbarDragLayer;
|
||||
final TaskbarView mTaskbarView;
|
||||
private final TaskbarDragLayer mTaskbarDragLayer;
|
||||
private final TaskbarView mTaskbarView;
|
||||
|
||||
private final AnimatedFloat mIconAlignmentForResumedState =
|
||||
new AnimatedFloat(this::onIconAlignmentRatioChanged);
|
||||
private final AnimatedFloat mIconAlignmentForGestureState =
|
||||
new AnimatedFloat(this::onIconAlignmentRatioChanged);
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
private AnimatedFloat mTaskbarBackgroundAlpha;
|
||||
private AlphaProperty mIconAlphaForHome;
|
||||
private boolean mIsAnimatingToLauncher;
|
||||
private boolean mIsAnimatingToLauncherViaResume;
|
||||
private boolean mIsAnimatingToLauncherViaGesture;
|
||||
private TaskbarKeyguardController mKeyguardController;
|
||||
|
||||
private LauncherState mTargetStateOverride = null;
|
||||
private TaskbarControllers mControllers;
|
||||
|
||||
public LauncherTaskbarUIController(
|
||||
BaseQuickstepLauncher launcher, TaskbarActivityContext context) {
|
||||
|
@ -80,13 +82,14 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
|||
|
||||
@Override
|
||||
protected void init(TaskbarControllers taskbarControllers) {
|
||||
mTaskbarBackgroundAlpha = taskbarControllers.taskbarDragLayerController
|
||||
.getTaskbarBackgroundAlpha();
|
||||
MultiValueAlpha taskbarIconAlpha = taskbarControllers.taskbarViewController
|
||||
.getTaskbarIconAlpha();
|
||||
mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
|
||||
mControllers = taskbarControllers;
|
||||
|
||||
mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
|
||||
.getTaskbarBackgroundAlpha();
|
||||
|
||||
MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
|
||||
mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
|
||||
|
||||
mHotseatController.init();
|
||||
mLauncher.setTaskbarUIController(this);
|
||||
mKeyguardController = taskbarControllers.taskbarKeyguardController;
|
||||
|
@ -109,19 +112,17 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
|||
|
||||
@Override
|
||||
protected boolean isTaskbarTouchable() {
|
||||
return !mIsAnimatingToLauncher && mTargetStateOverride == null;
|
||||
return !isAnimatingToLauncher() && !mControllers.taskbarStashController.isStashed();
|
||||
}
|
||||
|
||||
private boolean isAnimatingToLauncher() {
|
||||
return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateContentInsets(Rect outContentInsets) {
|
||||
// TaskbarDragLayer provides insets to other apps based on contentInsets. These
|
||||
// insets should stay consistent even if we expand TaskbarDragLayer's bounds, e.g.
|
||||
// to show a floating view like Folder. Thus, we set the contentInsets to be where
|
||||
// mTaskbarView is, since its position never changes and insets rather than overlays.
|
||||
outContentInsets.left = mTaskbarView.getLeft();
|
||||
outContentInsets.top = mTaskbarView.getTop();
|
||||
outContentInsets.right = mTaskbarDragLayer.getWidth() - mTaskbarView.getRight();
|
||||
outContentInsets.bottom = mTaskbarDragLayer.getHeight() - mTaskbarView.getBottom();
|
||||
int contentHeight = mControllers.taskbarStashController.getContentHeight();
|
||||
outContentInsets.top = mTaskbarDragLayer.getHeight() - contentHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,13 +138,20 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
|||
}
|
||||
}
|
||||
|
||||
long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
|
||||
ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
|
||||
getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
|
||||
.setDuration(QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
|
||||
.setDuration(duration);
|
||||
|
||||
anim.addListener(AnimatorListeners.forEndCallback(() -> mIsAnimatingToLauncher = false));
|
||||
anim.addListener(AnimatorListeners.forEndCallback(
|
||||
() -> mIsAnimatingToLauncherViaResume = false));
|
||||
anim.start();
|
||||
mIsAnimatingToLauncher = isResumed;
|
||||
mIsAnimatingToLauncherViaResume = isResumed;
|
||||
|
||||
if (!isResumed) {
|
||||
TaskbarStashController stashController = mControllers.taskbarStashController;
|
||||
stashController.animateToIsStashed(stashController.isStashedInApp(), duration);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,36 +163,48 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
|||
public Animator createAnimToLauncher(@NonNull LauncherState toState,
|
||||
@NonNull RecentsAnimationCallbacks callbacks,
|
||||
long duration) {
|
||||
TaskbarStashController stashController = mControllers.taskbarStashController;
|
||||
ObjectAnimator animator = mIconAlignmentForGestureState
|
||||
.animateToValue(mIconAlignmentForGestureState.value, 1)
|
||||
.animateToValue(1)
|
||||
.setDuration(duration);
|
||||
animator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mTargetStateOverride = null;
|
||||
animator.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mTargetStateOverride = toState;
|
||||
mIsAnimatingToLauncherViaGesture = true;
|
||||
// TODO: base this on launcher state
|
||||
stashController.animateToIsStashed(false, duration);
|
||||
}
|
||||
});
|
||||
callbacks.addListener(new RecentsAnimationListener() {
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
endGestureStateOverride();
|
||||
endGestureStateOverride(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
endGestureStateOverride();
|
||||
endGestureStateOverride(!controller.getFinishTargetIsLauncher());
|
||||
}
|
||||
|
||||
private void endGestureStateOverride() {
|
||||
private void endGestureStateOverride(boolean finishedToApp) {
|
||||
callbacks.removeListener(this);
|
||||
mIsAnimatingToLauncherViaGesture = false;
|
||||
|
||||
mIconAlignmentForGestureState
|
||||
.animateToValue(mIconAlignmentForGestureState.value, 0)
|
||||
.animateToValue(0)
|
||||
.start();
|
||||
|
||||
if (finishedToApp) {
|
||||
// We only need this for the exiting live tile case.
|
||||
stashController.animateToIsStashed(stashController.isStashedInApp());
|
||||
}
|
||||
}
|
||||
});
|
||||
return animator;
|
||||
|
@ -215,6 +235,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongPressToUnstashTaskbar() {
|
||||
return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called when one or more items in the Hotseat have changed.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* 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;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewOutlineProvider;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.RevealOutlineAnimation;
|
||||
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
||||
/**
|
||||
* Handles properties/data collection, then passes the results to our stashed handle View to render.
|
||||
*/
|
||||
public class StashedHandleViewController {
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final View mStashedHandleView;
|
||||
private final int mStashedHandleWidth;
|
||||
private final int mStashedHandleHeight;
|
||||
private final AnimatedFloat mTaskbarStashedHandleAlpha = new AnimatedFloat(
|
||||
this::updateStashedHandleAlpha);
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
|
||||
// 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;
|
||||
|
||||
private boolean mIsAtStashedRevealBounds = true;
|
||||
|
||||
public StashedHandleViewController(TaskbarActivityContext activity, View stashedHandleView) {
|
||||
mActivity = activity;
|
||||
mStashedHandleView = stashedHandleView;
|
||||
final Resources resources = mActivity.getResources();
|
||||
mStashedHandleWidth = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
|
||||
mStashedHandleHeight = resources.getDimensionPixelSize(
|
||||
R.dimen.taskbar_stashed_handle_height);
|
||||
}
|
||||
|
||||
public void init(TaskbarControllers controllers) {
|
||||
mControllers = controllers;
|
||||
mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
|
||||
|
||||
updateStashedHandleAlpha();
|
||||
|
||||
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);
|
||||
mStashedHandleRadius = view.getHeight() / 2f;
|
||||
outline.setRoundRect(mStashedHandleBounds, mStashedHandleRadius);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public AnimatedFloat getStashedHandleAlpha() {
|
||||
return mTaskbarStashedHandleAlpha;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public @Nullable Animator createRevealAnimToIsStashed(boolean isStashed) {
|
||||
if (mIsAtStashedRevealBounds == isStashed) {
|
||||
return null;
|
||||
}
|
||||
mIsAtStashedRevealBounds = isStashed;
|
||||
final RevealOutlineAnimation handleRevealProvider = new RoundedRectRevealOutlineProvider(
|
||||
mStashedHandleRadius, mStashedHandleRadius,
|
||||
mControllers.taskbarViewController.getIconLayoutBounds(), mStashedHandleBounds);
|
||||
return handleRevealProvider.createRevealAnimator(mStashedHandleView, !isStashed);
|
||||
}
|
||||
|
||||
protected void updateStashedHandleAlpha() {
|
||||
mStashedHandleView.setAlpha(mTaskbarStashedHandleAlpha.value);
|
||||
}
|
||||
}
|
|
@ -115,6 +115,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
|||
R.layout.taskbar, null, false);
|
||||
TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
|
||||
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
|
||||
View stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
|
||||
|
||||
// Construct controllers.
|
||||
mControllers = new TaskbarControllers(this,
|
||||
|
@ -125,7 +126,9 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
|
|||
R.color.popup_color_primary_light),
|
||||
new TaskbarDragLayerController(this, mDragLayer),
|
||||
new TaskbarViewController(this, taskbarView),
|
||||
new TaskbarKeyguardController(this));
|
||||
new TaskbarKeyguardController(this),
|
||||
new StashedHandleViewController(this, stashedHandleView),
|
||||
new TaskbarStashController(this));
|
||||
|
||||
Display display = windowContext.getDisplay();
|
||||
Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
|
||||
|
|
|
@ -32,6 +32,8 @@ public class TaskbarControllers {
|
|||
public final TaskbarDragLayerController taskbarDragLayerController;
|
||||
public final TaskbarViewController taskbarViewController;
|
||||
public final TaskbarKeyguardController taskbarKeyguardController;
|
||||
public final StashedHandleViewController stashedHandleViewController;
|
||||
public final TaskbarStashController taskbarStashController;
|
||||
|
||||
/** Do not store this controller, as it may change at runtime. */
|
||||
@NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
|
||||
|
@ -43,7 +45,9 @@ public class TaskbarControllers {
|
|||
RotationButtonController rotationButtonController,
|
||||
TaskbarDragLayerController taskbarDragLayerController,
|
||||
TaskbarViewController taskbarViewController,
|
||||
TaskbarKeyguardController taskbarKeyguardController) {
|
||||
TaskbarKeyguardController taskbarKeyguardController,
|
||||
StashedHandleViewController stashedHandleViewController,
|
||||
TaskbarStashController taskbarStashController) {
|
||||
this.taskbarActivityContext = taskbarActivityContext;
|
||||
this.taskbarDragController = taskbarDragController;
|
||||
this.navButtonController = navButtonController;
|
||||
|
@ -52,6 +56,8 @@ public class TaskbarControllers {
|
|||
this.taskbarDragLayerController = taskbarDragLayerController;
|
||||
this.taskbarViewController = taskbarViewController;
|
||||
this.taskbarKeyguardController = taskbarKeyguardController;
|
||||
this.stashedHandleViewController = stashedHandleViewController;
|
||||
this.taskbarStashController = taskbarStashController;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,6 +73,8 @@ public class TaskbarControllers {
|
|||
taskbarDragLayerController.init(this);
|
||||
taskbarViewController.init(this);
|
||||
taskbarKeyguardController.init(navbarButtonsViewController);
|
||||
stashedHandleViewController.init(this);
|
||||
taskbarStashController.init(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,10 +40,11 @@ import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInset
|
|||
public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
||||
|
||||
private final Paint mTaskbarBackgroundPaint;
|
||||
private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
|
||||
|
||||
private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
|
||||
|
||||
private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets;
|
||||
private float mTaskbarBackgroundOffset;
|
||||
|
||||
public TaskbarDragLayer(@NonNull Context context) {
|
||||
this(context, null);
|
||||
|
@ -118,8 +119,10 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
|||
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
canvas.drawRect(0, canvas.getHeight() - mControllerCallbacks.getTaskbarBackgroundHeight(),
|
||||
canvas.getWidth(), canvas.getHeight(), mTaskbarBackgroundPaint);
|
||||
float backgroundHeight = mControllerCallbacks.getTaskbarBackgroundHeight()
|
||||
* (1f - mTaskbarBackgroundOffset);
|
||||
canvas.drawRect(0, canvas.getHeight() - backgroundHeight, canvas.getWidth(),
|
||||
canvas.getHeight(), mTaskbarBackgroundPaint);
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
|
@ -132,6 +135,15 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
|
|||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the translation of the background color behind all the Taskbar contents.
|
||||
* @param offset 0 is fully onscreen, 1 is fully offscreen.
|
||||
*/
|
||||
protected void setTaskbarBackgroundOffset(float offset) {
|
||||
mTaskbarBackgroundOffset = offset;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
|
||||
|
|
|
@ -39,6 +39,8 @@ public class TaskbarDragLayerController {
|
|||
// Alpha properties for taskbar background.
|
||||
private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
|
||||
private final AnimatedFloat mBgNavbar = new AnimatedFloat(this::updateBackgroundAlpha);
|
||||
// Translation property for taskbar background.
|
||||
private final AnimatedFloat mBgOffset = new AnimatedFloat(this::updateBackgroundOffset);
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
|
@ -78,10 +80,18 @@ public class TaskbarDragLayerController {
|
|||
return mBgNavbar;
|
||||
}
|
||||
|
||||
public AnimatedFloat getTaskbarBackgroundOffset() {
|
||||
return mBgOffset;
|
||||
}
|
||||
|
||||
private void updateBackgroundAlpha() {
|
||||
mTaskbarDragLayer.setTaskbarBackgroundAlpha(Math.max(mBgNavbar.value, mBgTaskbar.value));
|
||||
}
|
||||
|
||||
private void updateBackgroundOffset() {
|
||||
mTaskbarDragLayer.setTaskbarBackgroundOffset(mBgOffset.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callbacks for {@link TaskbarDragLayer} to interact with its controller.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* 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 static android.view.HapticFeedbackConstants.LONG_PRESS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
||||
/**
|
||||
* Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
|
||||
* create a cohesive animation between stashed/unstashed states.
|
||||
*/
|
||||
public class TaskbarStashController {
|
||||
|
||||
/**
|
||||
* How long to stash/unstash when manually invoked via long press.
|
||||
*/
|
||||
private static final long TASKBAR_STASH_DURATION = 300;
|
||||
|
||||
/**
|
||||
* The scale TaskbarView animates to when being stashed.
|
||||
*/
|
||||
private static final float STASHED_TASKBAR_SCALE = 0.5f;
|
||||
|
||||
/**
|
||||
* The SharedPreferences key for whether user has manually stashed the taskbar.
|
||||
*/
|
||||
private static final String SHARED_PREFS_STASHED_KEY = "taskbar_is_stashed";
|
||||
|
||||
/**
|
||||
* Whether taskbar should be stashed out of the box.
|
||||
*/
|
||||
private static final boolean DEFAULT_STASHED_PREF = false;
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final SharedPreferences mPrefs;
|
||||
private final int mStashedHeight;
|
||||
private final int mUnstashedHeight;
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
// Taskbar background properties.
|
||||
private AnimatedFloat mTaskbarBackgroundOffset;
|
||||
// TaskbarView icon properties.
|
||||
private AlphaProperty mIconAlphaForStash;
|
||||
private AnimatedFloat mIconScaleForStash;
|
||||
private AnimatedFloat mIconTranslationYForStash;
|
||||
// Stashed handle properties.
|
||||
private AnimatedFloat mTaskbarStashedHandleAlpha;
|
||||
|
||||
/** Whether the user has manually invoked taskbar stashing, which we persist. */
|
||||
private boolean mIsStashedInApp;
|
||||
/** Whether we are currently visually stashed (might change based on launcher state). */
|
||||
private boolean mIsStashed = false;
|
||||
|
||||
private @Nullable AnimatorSet mAnimator;
|
||||
|
||||
public TaskbarStashController(TaskbarActivityContext activity) {
|
||||
mActivity = activity;
|
||||
mPrefs = Utilities.getPrefs(mActivity);
|
||||
final Resources resources = mActivity.getResources();
|
||||
mStashedHeight = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_size);
|
||||
mUnstashedHeight = mActivity.getDeviceProfile().taskbarSize;
|
||||
}
|
||||
|
||||
public void init(TaskbarControllers controllers) {
|
||||
mControllers = controllers;
|
||||
|
||||
TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController;
|
||||
mTaskbarBackgroundOffset = dragLayerController.getTaskbarBackgroundOffset();
|
||||
|
||||
TaskbarViewController taskbarViewController = controllers.taskbarViewController;
|
||||
mIconAlphaForStash = taskbarViewController.getTaskbarIconAlpha().getProperty(
|
||||
TaskbarViewController.ALPHA_INDEX_STASH);
|
||||
mIconScaleForStash = taskbarViewController.getTaskbarIconScaleForStash();
|
||||
mIconTranslationYForStash = taskbarViewController.getTaskbarIconTranslationYForStash();
|
||||
|
||||
StashedHandleViewController stashedHandleController =
|
||||
controllers.stashedHandleViewController;
|
||||
mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha();
|
||||
|
||||
mIsStashedInApp = supportsStashing()
|
||||
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user can manually stash the taskbar based on the current device state.
|
||||
*/
|
||||
private boolean supportsStashing() {
|
||||
return !mActivity.isThreeButtonNav();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the taskbar is currently visually stashed.
|
||||
*/
|
||||
public boolean isStashed() {
|
||||
return mIsStashed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user has manually stashed the taskbar in apps.
|
||||
*/
|
||||
public boolean isStashedInApp() {
|
||||
return mIsStashedInApp;
|
||||
}
|
||||
|
||||
public int getContentHeight() {
|
||||
return isStashed() ? mStashedHeight : mUnstashedHeight;
|
||||
}
|
||||
|
||||
public int getStashedHeight() {
|
||||
return mStashedHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called when long pressing the nav region when taskbar is present.
|
||||
* @return Whether taskbar was stashed and now is unstashed.
|
||||
*/
|
||||
public boolean onLongPressToUnstashTaskbar() {
|
||||
if (!isStashed()) {
|
||||
// We only listen for long press on the nav region to unstash the taskbar. To stash the
|
||||
// taskbar, we use an OnLongClickListener on TaskbarView instead.
|
||||
return false;
|
||||
}
|
||||
if (updateAndAnimateIsStashedInApp(false)) {
|
||||
mControllers.taskbarActivityContext.getDragLayer().performHapticFeedback(LONG_PRESS);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates whether we should stash the taskbar when in apps, and animates to the changed state.
|
||||
* @return Whether we started an animation to either be newly stashed or unstashed.
|
||||
*/
|
||||
public boolean updateAndAnimateIsStashedInApp(boolean isStashedInApp) {
|
||||
if (!supportsStashing()) {
|
||||
return false;
|
||||
}
|
||||
if (mIsStashedInApp != isStashedInApp) {
|
||||
boolean wasStashed = mIsStashedInApp;
|
||||
mIsStashedInApp = isStashedInApp;
|
||||
mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_KEY, mIsStashedInApp).apply();
|
||||
boolean isStashed = mIsStashedInApp;
|
||||
if (wasStashed != isStashed) {
|
||||
createAnimToIsStashed(isStashed, TASKBAR_STASH_DURATION).start();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an animation to the new stashed state with a default duration.
|
||||
*/
|
||||
public void animateToIsStashed(boolean isStashed) {
|
||||
animateToIsStashed(isStashed, TASKBAR_STASH_DURATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an animation to the new stashed state with the specified duration.
|
||||
*/
|
||||
public void animateToIsStashed(boolean isStashed, long duration) {
|
||||
createAnimToIsStashed(isStashed, duration).start();
|
||||
}
|
||||
|
||||
private Animator createAnimToIsStashed(boolean isStashed, long duration) {
|
||||
AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
|
||||
// Not exactly half and may overlap. See [first|second]HalfDurationScale below.
|
||||
AnimatorSet firstHalfAnimatorSet = new AnimatorSet();
|
||||
AnimatorSet secondHalfAnimatorSet = new AnimatorSet();
|
||||
|
||||
final float firstHalfDurationScale;
|
||||
final float secondHalfDurationScale;
|
||||
|
||||
if (isStashed) {
|
||||
firstHalfDurationScale = 0.75f;
|
||||
secondHalfDurationScale = 0.5f;
|
||||
final float stashTranslation = (mUnstashedHeight - mStashedHeight) / 2f;
|
||||
|
||||
fullLengthAnimatorSet.playTogether(
|
||||
mTaskbarBackgroundOffset.animateToValue(1),
|
||||
mIconTranslationYForStash.animateToValue(stashTranslation)
|
||||
);
|
||||
firstHalfAnimatorSet.playTogether(
|
||||
mIconAlphaForStash.animateToValue(0),
|
||||
mIconScaleForStash.animateToValue(STASHED_TASKBAR_SCALE)
|
||||
);
|
||||
secondHalfAnimatorSet.playTogether(
|
||||
mTaskbarStashedHandleAlpha.animateToValue(1)
|
||||
);
|
||||
} else {
|
||||
firstHalfDurationScale = 0.5f;
|
||||
secondHalfDurationScale = 0.75f;
|
||||
|
||||
fullLengthAnimatorSet.playTogether(
|
||||
mTaskbarBackgroundOffset.animateToValue(0),
|
||||
mIconScaleForStash.animateToValue(1),
|
||||
mIconTranslationYForStash.animateToValue(0)
|
||||
);
|
||||
firstHalfAnimatorSet.playTogether(
|
||||
mTaskbarStashedHandleAlpha.animateToValue(0)
|
||||
);
|
||||
secondHalfAnimatorSet.playTogether(
|
||||
mIconAlphaForStash.animateToValue(1)
|
||||
);
|
||||
}
|
||||
|
||||
Animator stashedHandleRevealAnim = mControllers.stashedHandleViewController
|
||||
.createRevealAnimToIsStashed(isStashed);
|
||||
if (stashedHandleRevealAnim != null) {
|
||||
fullLengthAnimatorSet.play(stashedHandleRevealAnim);
|
||||
}
|
||||
|
||||
fullLengthAnimatorSet.setDuration(duration);
|
||||
firstHalfAnimatorSet.setDuration((long) (duration * firstHalfDurationScale));
|
||||
secondHalfAnimatorSet.setDuration((long) (duration * secondHalfDurationScale));
|
||||
secondHalfAnimatorSet.setStartDelay((long) (duration * (1 - secondHalfDurationScale)));
|
||||
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
mAnimator = new AnimatorSet();
|
||||
mAnimator.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet,
|
||||
secondHalfAnimatorSet);
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
mIsStashed = isStashed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mAnimator = null;
|
||||
}
|
||||
});
|
||||
return mAnimator;
|
||||
}
|
||||
}
|
|
@ -33,4 +33,8 @@ public class TaskbarUIController {
|
|||
}
|
||||
|
||||
protected void updateContentInsets(Rect outContentInsets) { }
|
||||
|
||||
protected boolean onLongPressToUnstashTaskbar() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,8 +94,10 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
|||
|
||||
protected void init(TaskbarViewController.TaskbarViewCallbacks callbacks) {
|
||||
mControllerCallbacks = callbacks;
|
||||
mIconClickListener = mControllerCallbacks.getOnClickListener();
|
||||
mIconLongClickListener = mControllerCallbacks.getOnLongClickListener();
|
||||
mIconClickListener = mControllerCallbacks.getIconOnClickListener();
|
||||
mIconLongClickListener = mControllerCallbacks.getIconOnLongClickListener();
|
||||
|
||||
setOnLongClickListener(mControllerCallbacks.getBackgroundOnLongClickListener());
|
||||
}
|
||||
|
||||
private void removeAndRecycle(View view) {
|
||||
|
@ -235,6 +237,10 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
|||
return isShown() && mIconLayoutBounds.contains(xInOurCoordinates, yInOurCoorindates);
|
||||
}
|
||||
|
||||
public Rect getIconLayoutBounds() {
|
||||
return mIconLayoutBounds;
|
||||
}
|
||||
|
||||
// FolderIconParent implemented methods.
|
||||
|
||||
@Override
|
||||
|
|
|
@ -17,8 +17,8 @@ package com.android.launcher3.taskbar;
|
|||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.AnimatedFloat.VALUE;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
|
@ -28,6 +28,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
|
|||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
||||
/**
|
||||
* Handles properties/data collection, then passes the results to TaskbarView to render.
|
||||
|
@ -38,10 +39,16 @@ public class TaskbarViewController {
|
|||
public static final int ALPHA_INDEX_HOME = 0;
|
||||
public static final int ALPHA_INDEX_IME = 1;
|
||||
public static final int ALPHA_INDEX_KEYGUARD = 2;
|
||||
public static final int ALPHA_INDEX_STASH = 3;
|
||||
|
||||
private final TaskbarActivityContext mActivity;
|
||||
private final TaskbarView mTaskbarView;
|
||||
private final MultiValueAlpha mTaskbarIconAlpha;
|
||||
private final AnimatedFloat mTaskbarIconScaleForStash = new AnimatedFloat(this::updateScale);
|
||||
private final AnimatedFloat mTaskbarIconTranslationYForHome = new AnimatedFloat(
|
||||
this::updateTranslationY);
|
||||
private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
|
||||
this::updateTranslationY);
|
||||
|
||||
// Initialized in init.
|
||||
private TaskbarControllers mControllers;
|
||||
|
@ -54,7 +61,7 @@ public class TaskbarViewController {
|
|||
public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) {
|
||||
mActivity = activity;
|
||||
mTaskbarView = taskbarView;
|
||||
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, 3);
|
||||
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, 4);
|
||||
mTaskbarIconAlpha.setUpdateVisibility(true);
|
||||
}
|
||||
|
||||
|
@ -62,6 +69,8 @@ public class TaskbarViewController {
|
|||
mControllers = controllers;
|
||||
mTaskbarView.init(new TaskbarViewCallbacks());
|
||||
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
|
||||
|
||||
mTaskbarIconScaleForStash.updateValue(1f);
|
||||
}
|
||||
|
||||
public boolean areIconsVisible() {
|
||||
|
@ -86,6 +95,32 @@ public class TaskbarViewController {
|
|||
mTaskbarView.setClickAndLongClickListenersForIcon(icon);
|
||||
}
|
||||
|
||||
public Rect getIconLayoutBounds() {
|
||||
return mTaskbarView.getIconLayoutBounds();
|
||||
}
|
||||
|
||||
public AnimatedFloat getTaskbarIconScaleForStash() {
|
||||
return mTaskbarIconScaleForStash;
|
||||
}
|
||||
|
||||
public AnimatedFloat getTaskbarIconTranslationYForStash() {
|
||||
return mTaskbarIconTranslationYForStash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies scale properties for the entire TaskbarView (rather than individual icons).
|
||||
*/
|
||||
private void updateScale() {
|
||||
float scale = mTaskbarIconScaleForStash.value;
|
||||
mTaskbarView.setScaleX(scale);
|
||||
mTaskbarView.setScaleY(scale);
|
||||
}
|
||||
|
||||
private void updateTranslationY() {
|
||||
mTaskbarView.setTranslationY(mTaskbarIconTranslationYForHome.value
|
||||
+ mTaskbarIconTranslationYForStash.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the taskbar icon alignment relative to Launcher hotseat icons
|
||||
* @param alignmentRatio [0, 1]
|
||||
|
@ -116,7 +151,7 @@ public class TaskbarViewController {
|
|||
/ launcherDp.numShownHotseatIcons;
|
||||
|
||||
int offsetY = launcherDp.getTaskbarOffsetY();
|
||||
setter.setFloat(mTaskbarView, VIEW_TRANSLATE_Y, -offsetY, LINEAR);
|
||||
setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR);
|
||||
|
||||
int collapsedHeight = mActivity.getDeviceProfile().taskbarSize;
|
||||
int expandedHeight = collapsedHeight + offsetY;
|
||||
|
@ -144,12 +179,16 @@ public class TaskbarViewController {
|
|||
* Callbacks for {@link TaskbarView} to interact with its controller.
|
||||
*/
|
||||
public class TaskbarViewCallbacks {
|
||||
public View.OnClickListener getOnClickListener() {
|
||||
public View.OnClickListener getIconOnClickListener() {
|
||||
return mActivity::onTaskbarIconClicked;
|
||||
}
|
||||
|
||||
public View.OnLongClickListener getOnLongClickListener() {
|
||||
public View.OnLongClickListener getIconOnLongClickListener() {
|
||||
return mControllers.taskbarDragController::startDragOnLongClick;
|
||||
}
|
||||
|
||||
public View.OnLongClickListener getBackgroundOnLongClickListener() {
|
||||
return view -> mControllers.taskbarStashController.updateAndAnimateIsStashedInApp(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,16 @@ public class AnimatedFloat {
|
|||
mUpdateCallback = updateCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an animation from the current value to the given value.
|
||||
*/
|
||||
public ObjectAnimator animateToValue(float end) {
|
||||
return animateToValue(value, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an animation from the given start value to the given end value.
|
||||
*/
|
||||
public ObjectAnimator animateToValue(float start, float end) {
|
||||
cancelAnimation();
|
||||
mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end);
|
||||
|
|
|
@ -363,6 +363,14 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we detect a long press in the nav region before passing the gesture slop.
|
||||
* @return Whether taskbar handled the long press, and thus should cancel the gesture.
|
||||
*/
|
||||
public boolean onLongPressToUnstashTaskbar() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color of the scrim behind overview when at rest in this state.
|
||||
* Return {@link Color#TRANSPARENT} for no scrim.
|
||||
|
|
|
@ -39,6 +39,7 @@ public interface InputConsumer {
|
|||
int TYPE_OVERSCROLL = 1 << 9;
|
||||
int TYPE_SYSUI_OVERLAY = 1 << 10;
|
||||
int TYPE_ONE_HANDED = 1 << 11;
|
||||
int TYPE_TASKBAR_STASH = 1 << 12;
|
||||
|
||||
String[] NAMES = new String[] {
|
||||
"TYPE_NO_OP", // 0
|
||||
|
@ -53,6 +54,7 @@ public interface InputConsumer {
|
|||
"TYPE_OVERSCROLL", // 9
|
||||
"TYPE_SYSUI_OVERLAY", // 10
|
||||
"TYPE_ONE_HANDED", // 11
|
||||
"TYPE_TASKBAR_STASH", // 12
|
||||
};
|
||||
|
||||
InputConsumer NO_OP = () -> TYPE_NO_OP;
|
||||
|
|
|
@ -302,6 +302,15 @@ public final class LauncherActivityInterface extends
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onLongPressToUnstashTaskbar() {
|
||||
LauncherTaskbarUIController taskbarController = getTaskbarController();
|
||||
if (taskbarController == null) {
|
||||
return super.onLongPressToUnstashTaskbar();
|
||||
}
|
||||
return taskbarController.onLongPressToUnstashTaskbar();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getOverviewScrimColorForState(BaseQuickstepLauncher launcher,
|
||||
LauncherState state) {
|
||||
|
|
|
@ -46,6 +46,8 @@ public class RecentsAnimationController {
|
|||
private boolean mUseLauncherSysBarFlags = false;
|
||||
private boolean mSplitScreenMinimized = false;
|
||||
private boolean mFinishRequested = false;
|
||||
// Only valid when mFinishRequested == true.
|
||||
private boolean mFinishTargetIsLauncher;
|
||||
private RunnableList mPendingFinishCallbacks = new RunnableList();
|
||||
|
||||
public RecentsAnimationController(RecentsAnimationControllerCompat controller,
|
||||
|
@ -145,6 +147,7 @@ public class RecentsAnimationController {
|
|||
|
||||
// Finish not yet requested
|
||||
mFinishRequested = true;
|
||||
mFinishTargetIsLauncher = toRecents;
|
||||
mOnFinishedListener.accept(this);
|
||||
mPendingFinishCallbacks.add(callback);
|
||||
UI_HELPER_EXECUTOR.execute(() -> {
|
||||
|
@ -201,4 +204,12 @@ public class RecentsAnimationController {
|
|||
public RecentsAnimationControllerCompat getController() {
|
||||
return mController;
|
||||
}
|
||||
|
||||
/**
|
||||
* RecentsAnimationListeners can check this in onRecentsAnimationFinished() to determine whether
|
||||
* the animation was finished to launcher vs an app.
|
||||
*/
|
||||
public boolean getFinishTargetIsLauncher() {
|
||||
return mFinishTargetIsLauncher;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ import com.android.quickstep.inputconsumers.OverviewWithoutFocusInputConsumer;
|
|||
import com.android.quickstep.inputconsumers.ResetGestureInputConsumer;
|
||||
import com.android.quickstep.inputconsumers.ScreenPinnedInputConsumer;
|
||||
import com.android.quickstep.inputconsumers.SysUiOverlayInputConsumer;
|
||||
import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.AssistantUtilities;
|
||||
import com.android.quickstep.util.ProtoTracer;
|
||||
|
@ -673,6 +674,14 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
|||
mDeviceState, event);
|
||||
}
|
||||
|
||||
// If Taskbar is present, we listen for long press to unstash it.
|
||||
BaseActivityInterface activityInterface = newGestureState.getActivityInterface();
|
||||
StatefulActivity activity = activityInterface.getCreatedActivity();
|
||||
if (activity != null && activity.getDeviceProfile().isTaskbarPresent) {
|
||||
base = new TaskbarStashInputConsumer(this, base, mInputMonitorCompat,
|
||||
activityInterface);
|
||||
}
|
||||
|
||||
if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
|
||||
OverscrollPlugin plugin = null;
|
||||
if (FeatureFlags.FORCE_LOCAL_OVERSCROLL_PLUGIN.get()) {
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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.quickstep.inputconsumers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.quickstep.BaseActivityInterface;
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
|
||||
/**
|
||||
* Listens for a long press, and cancels the current gesture if that causes Taskbar to be unstashed.
|
||||
*/
|
||||
public class TaskbarStashInputConsumer extends DelegateInputConsumer {
|
||||
|
||||
private final BaseActivityInterface mActivityInterface;
|
||||
private final GestureDetector mLongPressDetector;
|
||||
|
||||
public TaskbarStashInputConsumer(Context context, InputConsumer delegate,
|
||||
InputMonitorCompat inputMonitor, BaseActivityInterface activityInterface) {
|
||||
super(delegate, inputMonitor);
|
||||
mActivityInterface = activityInterface;
|
||||
|
||||
mLongPressDetector = new GestureDetector(context, new SimpleOnGestureListener() {
|
||||
@Override
|
||||
public void onLongPress(MotionEvent motionEvent) {
|
||||
onLongPressDetected(motionEvent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return TYPE_TASKBAR_STASH | mDelegate.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionEvent(MotionEvent ev) {
|
||||
mLongPressDetector.onTouchEvent(ev);
|
||||
if (mState != STATE_ACTIVE) {
|
||||
mDelegate.onMotionEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLongPressDetected(MotionEvent motionEvent) {
|
||||
if (mActivityInterface.onLongPressToUnstashTaskbar()) {
|
||||
setActive(motionEvent);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.util.FloatProperty;
|
||||
import android.view.View;
|
||||
|
||||
|
@ -121,5 +123,12 @@ public class MultiValueAlpha {
|
|||
public String toString() {
|
||||
return Float.toString(mValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an Animator from the current value to the given value.
|
||||
*/
|
||||
public Animator animateToValue(float value) {
|
||||
return ObjectAnimator.ofFloat(this, VALUE, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue