mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 10:48:19 +00:00
The idea is that both taskbar icons and recents navigate you to new apps, which we'd want to disable in similar contexts. Hence reusing FLAG_DISABLE_RECENTS. Test: locally set FLAG_DISABLE_RECENTS=true, ensure taskbar icons don't show up (both in 3 button mode and gesture nav) Bug: 193183428 Bug: 194990283 Change-Id: I9537f57dc25663151b1414c5260dadb58506fdb0
251 lines
10 KiB
Java
251 lines
10 KiB
Java
/*
|
|
* 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 com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
|
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
|
import static com.android.launcher3.Utilities.squaredHypot;
|
|
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
|
import static com.android.quickstep.AnimatedFloat.VALUE;
|
|
|
|
import android.graphics.Rect;
|
|
import android.view.MotionEvent;
|
|
import android.view.View;
|
|
|
|
import com.android.launcher3.DeviceProfile;
|
|
import com.android.launcher3.LauncherAppState;
|
|
import com.android.launcher3.Utilities;
|
|
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.
|
|
*/
|
|
public class TaskbarViewController {
|
|
private static final Runnable NO_OP = () -> { };
|
|
|
|
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;
|
|
public static final int ALPHA_INDEX_RECENTS_DISABLED = 4;
|
|
private static final int NUM_ALPHA_CHANNELS = 5;
|
|
|
|
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);
|
|
|
|
private final TaskbarModelCallbacks mModelCallbacks;
|
|
|
|
// Initialized in init.
|
|
private TaskbarControllers mControllers;
|
|
|
|
// Animation to align icons with Launcher, created lazily. This allows the controller to be
|
|
// active only during the animation and does not need to worry about layout changes.
|
|
private AnimatorPlaybackController mIconAlignControllerLazy = null;
|
|
private Runnable mOnControllerPreCreateCallback = NO_OP;
|
|
|
|
public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) {
|
|
mActivity = activity;
|
|
mTaskbarView = taskbarView;
|
|
mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, NUM_ALPHA_CHANNELS);
|
|
mTaskbarIconAlpha.setUpdateVisibility(true);
|
|
mModelCallbacks = new TaskbarModelCallbacks(activity, mTaskbarView);
|
|
}
|
|
|
|
public void init(TaskbarControllers controllers) {
|
|
mControllers = controllers;
|
|
mTaskbarView.init(new TaskbarViewCallbacks());
|
|
mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
|
|
|
|
mTaskbarIconScaleForStash.updateValue(1f);
|
|
LauncherAppState.getInstance(mActivity).getModel().addCallbacksAndLoad(mModelCallbacks);
|
|
}
|
|
|
|
public void onDestroy() {
|
|
LauncherAppState.getInstance(mActivity).getModel().removeCallbacks(mModelCallbacks);
|
|
}
|
|
|
|
public boolean areIconsVisible() {
|
|
return mTaskbarView.areIconsVisible();
|
|
}
|
|
|
|
public MultiValueAlpha getTaskbarIconAlpha() {
|
|
return mTaskbarIconAlpha;
|
|
}
|
|
|
|
/**
|
|
* Should be called when the IME visibility changes, so we can make Taskbar not steal touches.
|
|
*/
|
|
public void setImeIsVisible(boolean isImeVisible) {
|
|
mTaskbarView.setTouchesEnabled(!isImeVisible);
|
|
}
|
|
|
|
/**
|
|
* Should be called when the recents button is disabled, so we can hide taskbar icons as well.
|
|
*/
|
|
public void setRecentsButtonDisabled(boolean isDisabled) {
|
|
// TODO: check TaskbarStashController#supportsStashing(), to stash instead of setting alpha.
|
|
mTaskbarIconAlpha.getProperty(ALPHA_INDEX_RECENTS_DISABLED).setValue(isDisabled ? 0 : 1);
|
|
}
|
|
|
|
/**
|
|
* Sets OnClickListener and OnLongClickListener for the given view.
|
|
*/
|
|
public void setClickAndLongClickListenersForIcon(View icon) {
|
|
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]
|
|
* 0 => not aligned
|
|
* 1 => fully aligned
|
|
*/
|
|
public void setLauncherIconAlignment(float alignmentRatio, DeviceProfile launcherDp) {
|
|
if (mIconAlignControllerLazy == null) {
|
|
mIconAlignControllerLazy = createIconAlignmentController(launcherDp);
|
|
}
|
|
mIconAlignControllerLazy.setPlayFraction(alignmentRatio);
|
|
if (alignmentRatio <= 0 || alignmentRatio >= 1) {
|
|
// Cleanup lazy controller so that it is created again in next animation
|
|
mIconAlignControllerLazy = null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates an animation for aligning the taskbar icons with the provided Launcher device profile
|
|
*/
|
|
private AnimatorPlaybackController createIconAlignmentController(DeviceProfile launcherDp) {
|
|
mOnControllerPreCreateCallback.run();
|
|
PendingAnimation setter = new PendingAnimation(100);
|
|
Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
|
|
float scaleUp = ((float) launcherDp.iconSizePx) / mActivity.getDeviceProfile().iconSizePx;
|
|
int hotseatCellSize =
|
|
(launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right)
|
|
/ launcherDp.numShownHotseatIcons;
|
|
|
|
int offsetY = launcherDp.getTaskbarOffsetY();
|
|
setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR);
|
|
|
|
int collapsedHeight = mActivity.getDefaultTaskbarWindowHeight();
|
|
int expandedHeight = Math.max(collapsedHeight,
|
|
mActivity.getDeviceProfile().taskbarSize + offsetY);
|
|
setter.addOnFrameListener(anim -> mActivity.setTaskbarWindowHeight(
|
|
anim.getAnimatedFraction() > 0 ? expandedHeight : collapsedHeight));
|
|
|
|
int count = mTaskbarView.getChildCount();
|
|
for (int i = 0; i < count; i++) {
|
|
View child = mTaskbarView.getChildAt(i);
|
|
ItemInfo info = (ItemInfo) child.getTag();
|
|
setter.setFloat(child, SCALE_PROPERTY, scaleUp, LINEAR);
|
|
|
|
float childCenter = (child.getLeft() + child.getRight()) / 2;
|
|
float hotseatIconCenter = hotseatPadding.left + hotseatCellSize * info.screenId
|
|
+ hotseatCellSize / 2;
|
|
setter.setFloat(child, VIEW_TRANSLATE_X, hotseatIconCenter - childCenter, LINEAR);
|
|
}
|
|
|
|
AnimatorPlaybackController controller = setter.createPlaybackController();
|
|
mOnControllerPreCreateCallback = () -> controller.setPlayFraction(0);
|
|
return controller;
|
|
}
|
|
|
|
/**
|
|
* Callbacks for {@link TaskbarView} to interact with its controller.
|
|
*/
|
|
public class TaskbarViewCallbacks {
|
|
private final float mSquaredTouchSlop = Utilities.squaredTouchSlop(mActivity);
|
|
|
|
private float mDownX, mDownY;
|
|
private boolean mCanceledStashHint;
|
|
|
|
public View.OnClickListener getIconOnClickListener() {
|
|
return mActivity::onTaskbarIconClicked;
|
|
}
|
|
|
|
public View.OnLongClickListener getIconOnLongClickListener() {
|
|
return mControllers.taskbarDragController::startDragOnLongClick;
|
|
}
|
|
|
|
public View.OnLongClickListener getBackgroundOnLongClickListener() {
|
|
return view -> mControllers.taskbarStashController.updateAndAnimateIsStashedInApp(true);
|
|
}
|
|
|
|
public void onTouchEvent(MotionEvent motionEvent) {
|
|
final float x = motionEvent.getRawX();
|
|
final float y = motionEvent.getRawY();
|
|
switch (motionEvent.getAction()) {
|
|
case MotionEvent.ACTION_DOWN:
|
|
mDownX = x;
|
|
mDownY = y;
|
|
mControllers.taskbarStashController.startStashHint(/* animateForward = */ true);
|
|
mCanceledStashHint = false;
|
|
break;
|
|
case MotionEvent.ACTION_MOVE:
|
|
if (!mCanceledStashHint
|
|
&& squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
|
|
mControllers.taskbarStashController.startStashHint(
|
|
/* animateForward= */ false);
|
|
mCanceledStashHint = true;
|
|
}
|
|
break;
|
|
case MotionEvent.ACTION_UP:
|
|
case MotionEvent.ACTION_CANCEL:
|
|
if (!mCanceledStashHint) {
|
|
mControllers.taskbarStashController.startStashHint(
|
|
/* animateForward= */ false);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|