diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 79af7cc5dd..9a836aa255 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -16,9 +16,12 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_HOME; +import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_LAUNCHER_STATE; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; +import android.graphics.Rect; import android.view.MotionEvent; import androidx.annotation.NonNull; @@ -30,6 +33,7 @@ import com.android.launcher3.QuickstepTransitionManager; import com.android.launcher3.R; import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.PendingAnimation; +import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.AnimatedFloat; @@ -47,7 +51,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { final TaskbarDragLayer mTaskbarDragLayer; final TaskbarView mTaskbarView; - private AnimatedFloat mTaskBarAlpha; + private AnimatedFloat mTaskbarBackgroundAlpha; private AlphaProperty mIconAlphaForHome; private @Nullable Animator mAnimator; private boolean mIsAnimatingToLauncher; @@ -66,11 +70,14 @@ public class LauncherTaskbarUIController extends TaskbarUIController { } @Override - protected void init(AnimatedFloat taskBarAlpha, AlphaProperty iconAlphaForLauncherState, - AlphaProperty iconAlphaForHome) { - mTaskBarAlpha = taskBarAlpha; - mIconAlphaForHome = iconAlphaForHome; - mTaskbarStateHandler.setAnimationController(iconAlphaForLauncherState); + protected void init(TaskbarControllers taskbarControllers) { + mTaskbarBackgroundAlpha = taskbarControllers.taskbarDragLayerController + .getTaskbarBackgroundAlpha(); + MultiValueAlpha taskbarIconAlpha = taskbarControllers.taskbarViewController + .getTaskbarIconAlpha(); + mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME); + mTaskbarStateHandler.setAnimationController(taskbarIconAlpha.getProperty( + ALPHA_INDEX_LAUNCHER_STATE)); mHotseatController.init(); setTaskbarViewVisible(!mLauncher.hasBeenResumed()); mLauncher.setTaskbarUIController(this); @@ -94,6 +101,18 @@ public class LauncherTaskbarUIController extends TaskbarUIController { return !mIsAnimatingToLauncher; } + @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(); + } + /** * Should be called from onResume() and onPause(), and animates the Taskbar accordingly. */ @@ -125,7 +144,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { PendingAnimation anim = new PendingAnimation(duration); mTaskbarStateHandler.setState(toState, anim); - anim.setFloat(mTaskBarAlpha, AnimatedFloat.VALUE, 0, LINEAR); + anim.setFloat(mTaskbarBackgroundAlpha, AnimatedFloat.VALUE, 0, LINEAR); mTaskbarView.alignIconsWithLauncher(mLauncher.getDeviceProfile(), anim); anim.addListener(new AnimatorListenerAdapter() { @@ -146,7 +165,7 @@ public class LauncherTaskbarUIController extends TaskbarUIController { private Animator createAnimToApp(long duration) { PendingAnimation anim = new PendingAnimation(duration); - anim.setFloat(mTaskBarAlpha, AnimatedFloat.VALUE, 1, LINEAR); + anim.setFloat(mTaskbarBackgroundAlpha, AnimatedFloat.VALUE, 1, LINEAR); anim.addListener(AnimatorListeners.forEndCallback(mTaskbarView.resetIconPosition(anim))); anim.addListener(new AnimatorListenerAdapter() { @Override diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonUIController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java similarity index 86% rename from quickstep/src/com/android/launcher3/taskbar/NavbarButtonUIController.java rename to quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index dc292a1816..2ae7d108ed 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -21,6 +21,7 @@ import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BA import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME; import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH; import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS; +import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_IME; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING; @@ -48,7 +49,6 @@ import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton; import com.android.launcher3.taskbar.contextual.RotationButton; import com.android.launcher3.taskbar.contextual.RotationButtonController; import com.android.launcher3.util.MultiValueAlpha; -import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.AnimatedFloat; import java.util.ArrayList; @@ -57,7 +57,7 @@ import java.util.function.IntPredicate; /** * Controller for managing nav bar buttons in taskbar */ -public class NavbarButtonUIController { +public class NavbarButtonsViewController { private final Rect mTempRect = new Rect(); @@ -74,48 +74,53 @@ public class NavbarButtonUIController { private int mState; private final TaskbarActivityContext mContext; - private View a11yButton; + private final FrameLayout mNavButtonsView; + private final ViewGroup mStartContainer; + private final ViewGroup mEndContainer; + + // Initialized in init. + private TaskbarControllers mControllers; + private View mA11yButton; private int mSysuiStateFlags; - public NavbarButtonUIController(TaskbarActivityContext context) { + public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) { mContext = context; + mNavButtonsView = navButtonsView; + mStartContainer = mNavButtonsView.findViewById(R.id.start_nav_buttons); + mEndContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons); } /** * Initializes the controller */ - public void init(TaskbarDragLayer dragLayer, - TaskbarNavButtonController navButtonController, - RotationButtonController rotationButtonController, - AnimatedFloat taskbarBackgroundAlpha, AlphaProperty taskbarIconAlpha) { - FrameLayout buttonController = dragLayer.findViewById(R.id.navbuttons_view); - buttonController.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize; + public void init(TaskbarControllers controllers) { + mControllers = controllers; + mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize; mA11yLongClickListener = view -> { - navButtonController.onButtonClick(BUTTON_A11Y_LONG_CLICK); + mControllers.navButtonController.onButtonClick(BUTTON_A11Y_LONG_CLICK); return true; }; if (mContext.canShowNavButtons()) { - ViewGroup startContainer = buttonController.findViewById(R.id.start_nav_buttons); - ViewGroup endContainer = buttonController.findViewById(R.id.end_nav_buttons); - - initButtons(startContainer, endContainer, navButtonController); + initButtons(mStartContainer, mEndContainer, mControllers.navButtonController); // Animate taskbar background when IME shows - mPropertyHolders.add(new StatePropertyHolder(taskbarBackgroundAlpha, + mPropertyHolders.add(new StatePropertyHolder( + mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(), flags -> (flags & FLAG_IME_VISIBLE) == 0, AnimatedFloat.VALUE, 0, 1)); mPropertyHolders.add(new StatePropertyHolder( - taskbarIconAlpha, flags -> (flags & FLAG_IME_VISIBLE) == 0, - MultiValueAlpha.VALUE, 1, 0)); + mControllers.taskbarViewController.getTaskbarIconAlpha() + .getProperty(ALPHA_INDEX_IME), + flags -> (flags & FLAG_IME_VISIBLE) == 0, MultiValueAlpha.VALUE, 1, 0)); // Rotation button - RotationButton rotationButton = new RotationButtonImpl(addButton(endContainer)); + RotationButton rotationButton = new RotationButtonImpl(addButton(mEndContainer)); rotationButton.hide(); - rotationButtonController.setRotationButton(rotationButton); + mControllers.rotationButtonController.setRotationButton(rotationButton); } else { - rotationButtonController.setRotationButton(new RotationButton() { }); + mControllers.rotationButtonController.setRotationButton(new RotationButton() {}); } applyState(); @@ -151,12 +156,12 @@ public class NavbarButtonUIController { && ((flags & FLAG_A11Y_VISIBLE) == 0))); // A11y button - a11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y, + mA11yButton = addButton(R.drawable.ic_sysbar_accessibility_button, BUTTON_A11Y, endContainer, navButtonController); - mPropertyHolders.add(new StatePropertyHolder(a11yButton, + mPropertyHolders.add(new StatePropertyHolder(mA11yButton, flags -> (flags & FLAG_A11Y_VISIBLE) != 0 && (flags & FLAG_ROTATION_BUTTON_VISIBLE) == 0)); - a11yButton.setOnLongClickListener(mA11yLongClickListener); + mA11yButton.setOnLongClickListener(mA11yLongClickListener); } public void updateStateForSysuiFlags(int systemUiStateFlags, boolean forceUpdate) { @@ -174,7 +179,7 @@ public class NavbarButtonUIController { updateStateForFlag(FLAG_IME_VISIBLE, isImeVisible); updateStateForFlag(FLAG_SWITCHER_SUPPORTED, isImeSwitcherShowing); updateStateForFlag(FLAG_A11Y_VISIBLE, a11yVisible); - a11yButton.setLongClickable(a11yLongClickable); + mA11yButton.setLongClickable(a11yLongClickable); applyState(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index a25eb38d99..6e477000dd 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -38,6 +38,7 @@ import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.WindowManager; +import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.NonNull; @@ -52,12 +53,10 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.taskbar.contextual.RotationButtonController; import com.android.launcher3.touch.ItemClickHandler; -import com.android.launcher3.util.MultiValueAlpha; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.Themes; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.ActivityContext; -import com.android.quickstep.AnimatedFloat; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.systemui.shared.recents.model.Task; @@ -77,16 +76,10 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ private static final String WINDOW_TITLE = "Taskbar"; - private static final int ALPHA_INDEX_HOME = 0; - private static final int ALPHA_INDEX_LAUNCHER_STATE = 1; - private static final int ALPHA_INDEX_IME = 2; - private final DeviceProfile mDeviceProfile; private final LayoutInflater mLayoutInflater; private final TaskbarDragLayer mDragLayer; - private final TaskbarIconController mIconController; - private final TaskbarDragController mDragController; - private final NavbarButtonUIController mNavbarButtonUIController; + private final TaskbarControllers mControllers; private final WindowManager mWindowManager; private WindowManager.LayoutParams mWindowLayoutParams; @@ -95,57 +88,46 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ private int mLastRequestedNonFullscreenHeight; private final SysUINavigationMode.Mode mNavMode; - private final TaskbarNavButtonController mNavButtonController; - private final RotationButtonController mRotationButtonController; private final boolean mIsSafeModeEnabled; - @NonNull - private TaskbarUIController mUIController = TaskbarUIController.DEFAULT; - - private final View.OnClickListener mOnTaskbarIconClickListener; - private final View.OnLongClickListener mOnTaskbarIconLongClickListener; - - // Alpha property for task bar - private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha); - private final AnimatedFloat mBgNavbar = new AnimatedFloat(this::updateBackgroundAlpha); - - private final MultiValueAlpha mTaskbarIconAlpha; - public TaskbarActivityContext(Context windowContext, DeviceProfile dp, TaskbarNavButtonController buttonController) { super(windowContext, Themes.getActivityThemeRes(windowContext)); mDeviceProfile = dp; - mNavButtonController = buttonController; + mNavMode = SysUINavigationMode.getMode(windowContext); mIsSafeModeEnabled = TraceHelper.allowIpcs("isSafeMode", () -> getPackageManager().isSafeMode()); - mDragController = new TaskbarDragController(this); - mOnTaskbarIconLongClickListener = mDragController::startDragOnLongClick; - mOnTaskbarIconClickListener = this::onTaskbarIconClicked; - float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size); mDeviceProfile.updateIconSize(1, getResources()); float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx; mDeviceProfile.updateIconSize(iconScale, getResources()); mLayoutInflater = LayoutInflater.from(this).cloneInContext(this); - mDragLayer = (TaskbarDragLayer) mLayoutInflater - .inflate(R.layout.taskbar, null, false); - mRotationButtonController = new RotationButtonController(this, - R.color.popup_color_primary_light, R.color.popup_color_primary_light); - mNavbarButtonUIController = new NavbarButtonUIController(this); - mIconController = new TaskbarIconController(this, mDragLayer, mNavbarButtonUIController); + + // Inflate views. + mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate( + R.layout.taskbar, null, false); + TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view); + FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view); + + // Construct controllers. + mControllers = new TaskbarControllers(this, + new TaskbarDragController(this), + buttonController, + new NavbarButtonsViewController(this, navButtonsView), + new RotationButtonController(this, R.color.popup_color_primary_light, + R.color.popup_color_primary_light), + new TaskbarDragLayerController(this, mDragLayer), + new TaskbarViewController(this, taskbarView)); Display display = windowContext.getDisplay(); Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY ? windowContext.getApplicationContext() : windowContext.getApplicationContext().createDisplayContext(display); mWindowManager = c.getSystemService(WindowManager.class); - - mTaskbarIconAlpha = new MultiValueAlpha(mDragLayer.findViewById(R.id.taskbar_view), 3); - mTaskbarIconAlpha.setUpdateVisibility(true); } public void init() { @@ -170,13 +152,10 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ new int[] { ITYPE_EXTRA_NAVIGATION_BAR, ITYPE_BOTTOM_TAPPABLE_ELEMENT } ); - mIconController.init(mOnTaskbarIconClickListener, mOnTaskbarIconLongClickListener); - mNavbarButtonUIController.init(mDragLayer, mNavButtonController, mRotationButtonController, - mBgNavbar, mTaskbarIconAlpha.getProperty(ALPHA_INDEX_IME)); + // Initialize controllers after all are constructed. + mControllers.init(); + mWindowManager.addView(mDragLayer, mWindowLayoutParams); - if (canShowNavButtons()) { - mRotationButtonController.init(); - } } public boolean canShowNavButtons() { @@ -200,23 +179,21 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ @Override public Rect getFolderBoundingBox() { - return mDragLayer.getFolderBoundingBox(); + return mControllers.taskbarDragLayerController.getFolderBoundingBox(); } @Override public TaskbarDragController getDragController() { - return mDragController; + return mControllers.taskbarDragController; } /** * Sets a new data-source for this taskbar instance */ public void setUIController(@NonNull TaskbarUIController uiController) { - mUIController.onDestroy(); - mUIController = uiController; - mIconController.setUIController(mUIController); - mUIController.init(mBgTaskbar, mTaskbarIconAlpha.getProperty(ALPHA_INDEX_LAUNCHER_STATE), - mTaskbarIconAlpha.getProperty(ALPHA_INDEX_HOME)); + mControllers.uiController.onDestroy(); + mControllers.uiController = uiController; + mControllers.uiController.init(mControllers); } /** @@ -224,8 +201,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ */ public void onDestroy() { setUIController(TaskbarUIController.DEFAULT); - mIconController.onDestroy(); - mRotationButtonController.onDestroy(); + mControllers.onDestroy(); mWindowManager.removeViewImmediate(mDragLayer); } @@ -233,23 +209,25 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ if (!canShowNavButtons()) { return; } - mNavbarButtonUIController.updateStateForSysuiFlags(systemUiStateFlags, forceUpdate); - mIconController.setImeIsVisible(mNavbarButtonUIController.isImeVisible()); + mControllers.navbarButtonsViewController.updateStateForSysuiFlags( + systemUiStateFlags, forceUpdate); + mControllers.taskbarViewController.setImeIsVisible( + mControllers.navbarButtonsViewController.isImeVisible()); } public void onRotationProposal(int rotation, boolean isValid) { - mRotationButtonController.onRotationProposal(rotation, isValid); + mControllers.rotationButtonController.onRotationProposal(rotation, isValid); } public void disable(int displayId, int state1, int state2, boolean animate) { if (displayId != getDisplayId()) { return; } - mRotationButtonController.onDisable2FlagChanged(state2); + mControllers.rotationButtonController.onDisable2FlagChanged(state2); } public void onSystemBarAttributesChanged(int displayId, int behavior) { - mRotationButtonController.onBehaviorChanged(displayId, behavior); + mControllers.rotationButtonController.onBehaviorChanged(displayId, behavior); } /** @@ -296,8 +274,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ folder.animateOpen(); folder.iterateOverItems((itemInfo, itemView) -> { - itemView.setOnClickListener(mOnTaskbarIconClickListener); - itemView.setOnLongClickListener(mOnTaskbarIconLongClickListener); + mControllers.taskbarViewController + .setClickAndLongClickListenersForIcon(itemView); // To play haptic when dragging, like other Taskbar items do. itemView.setHapticFeedbackEnabled(true); return false; @@ -343,9 +321,4 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ AbstractFloatingView.closeAllOpenViews(this); } - - private void updateBackgroundAlpha() { - mDragLayer.setTaskbarBackgroundAlpha(Math.max(mBgNavbar.value, mBgTaskbar.value)); - } - } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java new file mode 100644 index 0000000000..7712ffef55 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -0,0 +1,76 @@ +/* + * 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 androidx.annotation.NonNull; + +import com.android.launcher3.taskbar.contextual.RotationButtonController; + +/** + * Hosts various taskbar controllers to facilitate passing between one another. + */ +public class TaskbarControllers { + + public final TaskbarActivityContext taskbarActivityContext; + public final TaskbarDragController taskbarDragController; + public final TaskbarNavButtonController navButtonController; + public final NavbarButtonsViewController navbarButtonsViewController; + public final RotationButtonController rotationButtonController; + public final TaskbarDragLayerController taskbarDragLayerController; + public final TaskbarViewController taskbarViewController; + + /** Do not store this controller, as it may change at runtime. */ + @NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT; + + public TaskbarControllers(TaskbarActivityContext taskbarActivityContext, + TaskbarDragController taskbarDragController, + TaskbarNavButtonController navButtonController, + NavbarButtonsViewController navbarButtonsViewController, + RotationButtonController rotationButtonController, + TaskbarDragLayerController taskbarDragLayerController, + TaskbarViewController taskbarViewController) { + this.taskbarActivityContext = taskbarActivityContext; + this.taskbarDragController = taskbarDragController; + this.navButtonController = navButtonController; + this.navbarButtonsViewController = navbarButtonsViewController; + this.rotationButtonController = rotationButtonController; + this.taskbarDragLayerController = taskbarDragLayerController; + this.taskbarViewController = taskbarViewController; + } + + /** + * Initializes all controllers. Note that controllers can now reference each other through this + * TaskbarControllers instance, but should be careful to only access things that were created + * in constructors for now, as some controllers may still be waiting for init(). + */ + public void init() { + navbarButtonsViewController.init(this); + if (taskbarActivityContext.canShowNavButtons()) { + rotationButtonController.init(); + } + taskbarDragLayerController.init(this); + taskbarViewController.init(this); + } + + /** + * Cleans up all controllers. + */ + public void onDestroy() { + uiController.onDestroy(); + rotationButtonController.onDestroy(); + taskbarDragLayerController.onDestroy(); + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java index 52a2c86c76..c6845434a1 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java @@ -18,7 +18,6 @@ package com.android.launcher3.taskbar; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; -import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; @@ -37,11 +36,9 @@ import com.android.systemui.shared.system.ViewTreeObserverWrapper.OnComputeInset */ public class TaskbarDragLayer extends BaseDragLayer { - private final int mFolderMargin; private final Paint mTaskbarBackgroundPaint; - private TaskbarIconController.TaskbarDragLayerCallbacks mControllerCallbacks; - private TaskbarView mTaskbarView; + private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks; private final OnComputeInsetsListener mTaskbarInsetsComputer = this::onComputeTaskbarInsets; @@ -61,10 +58,13 @@ public class TaskbarDragLayer extends BaseDragLayer { public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, 1 /* alphaChannelCount */); - mFolderMargin = getResources().getDimensionPixelSize(R.dimen.taskbar_folder_margin); mTaskbarBackgroundPaint = new Paint(); mTaskbarBackgroundPaint.setColor(getResources().getColor(R.color.taskbar_background)); mTaskbarBackgroundPaint.setAlpha(0); + } + + public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) { + mControllerCallbacks = callbacks; recreateControllers(); } @@ -73,15 +73,10 @@ public class TaskbarDragLayer extends BaseDragLayer { mControllers = new TouchController[] {mActivity.getDragController()}; } - public void init(TaskbarIconController.TaskbarDragLayerCallbacks callbacks, - TaskbarView taskbarView) { - mControllerCallbacks = callbacks; - mTaskbarView = taskbarView; - } - private void onComputeTaskbarInsets(InsetsInfo insetsInfo) { if (mControllerCallbacks != null) { mControllerCallbacks.updateInsetsTouchability(insetsInfo); + mControllerCallbacks.updateContentInsets(insetsInfo.contentInsets); } } @@ -120,20 +115,11 @@ public class TaskbarDragLayer extends BaseDragLayer { @Override protected void dispatchDraw(Canvas canvas) { - canvas.drawRect(0, canvas.getHeight() - mTaskbarView.getHeight(), canvas.getWidth(), - canvas.getHeight(), mTaskbarBackgroundPaint); + canvas.drawRect(0, canvas.getHeight() - mControllerCallbacks.getTaskbarBackgroundHeight(), + canvas.getWidth(), canvas.getHeight(), mTaskbarBackgroundPaint); super.dispatchDraw(canvas); } - /** - * @return Bounds (in our coordinates) where an opened Folder can display. - */ - protected Rect getFolderBoundingBox() { - Rect boundingBox = new Rect(0, 0, getWidth(), getHeight() - mTaskbarView.getHeight()); - boundingBox.inset(mFolderMargin, mFolderMargin); - return boundingBox; - } - /** * Sets the alpha of the background color behind all the Taskbar contents. * @param alpha 0 is fully transparent, 1 is fully opaque. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java new file mode 100644 index 0000000000..2efbd4fa37 --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java @@ -0,0 +1,137 @@ +/* + * 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.AbstractFloatingView.TYPE_ALL; +import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME; +import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION; + +import android.content.res.Resources; +import android.graphics.Rect; + +import com.android.launcher3.AbstractFloatingView; +import com.android.launcher3.R; +import com.android.launcher3.anim.AlphaUpdateListener; +import com.android.quickstep.AnimatedFloat; +import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo; + +/** + * Handles properties/data collection, then passes the results to TaskbarDragLayer to render. + */ +public class TaskbarDragLayerController { + + private final TaskbarActivityContext mActivity; + private final TaskbarDragLayer mTaskbarDragLayer; + private final int mFolderMargin; + // Alpha properties for taskbar background. + private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha); + private final AnimatedFloat mBgNavbar = new AnimatedFloat(this::updateBackgroundAlpha); + + // Initialized in init. + private TaskbarControllers mControllers; + + public TaskbarDragLayerController(TaskbarActivityContext activity, + TaskbarDragLayer taskbarDragLayer) { + mActivity = activity; + mTaskbarDragLayer = taskbarDragLayer; + final Resources resources = mTaskbarDragLayer.getResources(); + mFolderMargin = resources.getDimensionPixelSize(R.dimen.taskbar_folder_margin); + } + + public void init(TaskbarControllers controllers) { + mControllers = controllers; + mTaskbarDragLayer.init(new TaskbarDragLayerCallbacks()); + } + + public void onDestroy() { + mTaskbarDragLayer.onDestroy(); + } + + /** + * @return Bounds (in TaskbarDragLayer coordinates) where an opened Folder can display. + */ + public Rect getFolderBoundingBox() { + Rect boundingBox = new Rect(0, 0, mTaskbarDragLayer.getWidth(), + mTaskbarDragLayer.getHeight() - mActivity.getDeviceProfile().taskbarSize); + boundingBox.inset(mFolderMargin, mFolderMargin); + return boundingBox; + } + + public AnimatedFloat getTaskbarBackgroundAlpha() { + return mBgTaskbar; + } + + public AnimatedFloat getNavbarBackgroundAlpha() { + return mBgNavbar; + } + + private void updateBackgroundAlpha() { + mTaskbarDragLayer.setTaskbarBackgroundAlpha(Math.max(mBgNavbar.value, mBgTaskbar.value)); + } + + /** + * Callbacks for {@link TaskbarDragLayer} to interact with its controller. + */ + public class TaskbarDragLayerCallbacks { + + /** + * Called to update the touchable insets. + * @see InsetsInfo#setTouchableInsets(int) + */ + public void updateInsetsTouchability(InsetsInfo insetsInfo) { + insetsInfo.touchableRegion.setEmpty(); + if (mTaskbarDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) { + // Let touches pass through us. + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); + } else if (mControllers.navbarButtonsViewController.isImeVisible()) { + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME); + } else if (!mControllers.uiController.isTaskbarTouchable()) { + // Let touches pass through us. + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); + } else if (mControllers.taskbarViewController.areIconsVisible()) { + // Buttons are visible, take over the full taskbar area + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME); + } else { + mControllers.navbarButtonsViewController.addVisibleButtonsRegion( + mTaskbarDragLayer, insetsInfo.touchableRegion); + insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); + } + } + + /** + * Called to update the {@link InsetsInfo#contentInsets}. + */ + public void updateContentInsets(Rect outContentInsets) { + mControllers.uiController.updateContentInsets(outContentInsets); + } + + /** + * Called when a child is removed from TaskbarDragLayer. + */ + public void onDragLayerViewRemoved() { + if (AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) == null) { + mActivity.setTaskbarWindowFullscreen(false); + } + } + + /** + * Returns how tall the background should be drawn at the bottom of the screen. + */ + public int getTaskbarBackgroundHeight() { + return mActivity.getDeviceProfile().taskbarSize; + } + } +} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java deleted file mode 100644 index 7dca19c262..0000000000 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarIconController.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * 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.AbstractFloatingView.TYPE_ALL; -import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_FRAME; -import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION; - -import android.view.View.OnClickListener; -import android.view.View.OnLongClickListener; - -import androidx.annotation.NonNull; - -import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.R; -import com.android.launcher3.anim.AlphaUpdateListener; -import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo; - -/** - * Controller for taskbar icon UI - */ -public class TaskbarIconController { - - private final TaskbarActivityContext mActivity; - private final TaskbarDragLayer mDragLayer; - private final NavbarButtonUIController mNavbarButtonUIController; - - private final TaskbarView mTaskbarView; - - @NonNull - private TaskbarUIController mUIController = TaskbarUIController.DEFAULT; - - TaskbarIconController(TaskbarActivityContext activity, TaskbarDragLayer dragLayer, - NavbarButtonUIController navbarButtonUIController) { - mActivity = activity; - mDragLayer = dragLayer; - mNavbarButtonUIController = navbarButtonUIController; - mTaskbarView = mDragLayer.findViewById(R.id.taskbar_view); - } - - public void init(OnClickListener clickListener, OnLongClickListener longClickListener) { - mTaskbarView.init(clickListener, longClickListener); - mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize; - - mDragLayer.init(new TaskbarDragLayerCallbacks(), mTaskbarView); - } - - public void onDestroy() { - mDragLayer.onDestroy(); - } - - public void setUIController(@NonNull TaskbarUIController uiController) { - mUIController = uiController; - } - - /** - * Should be called when the IME visibility changes, so we can hide/show Taskbar accordingly. - */ - public void setImeIsVisible(boolean isImeVisible) { - mTaskbarView.setTouchesEnabled(!isImeVisible); - } - - /** - * Callbacks for {@link TaskbarDragLayer} to interact with the icon controller - */ - public class TaskbarDragLayerCallbacks { - - /** - * Called to update the touchable insets - */ - public void updateInsetsTouchability(InsetsInfo insetsInfo) { - insetsInfo.touchableRegion.setEmpty(); - if (mDragLayer.getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD) { - // Let touches pass through us. - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (mNavbarButtonUIController.isImeVisible()) { - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME); - } else if (!mUIController.isTaskbarTouchable()) { - // Let touches pass through us. - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } else if (mTaskbarView.areIconsVisible()) { - // Buttons are visible, take over the full taskbar area - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_FRAME); - } else { - mNavbarButtonUIController.addVisibleButtonsRegion( - mDragLayer, insetsInfo.touchableRegion); - insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION); - } - - // TaskbarContainerView provides insets to other apps based on contentInsets. These - // insets should stay consistent even if we expand TaskbarContainerView'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. - insetsInfo.contentInsets.left = mTaskbarView.getLeft(); - insetsInfo.contentInsets.top = mTaskbarView.getTop(); - insetsInfo.contentInsets.right = mDragLayer.getWidth() - mTaskbarView.getRight(); - insetsInfo.contentInsets.bottom = mDragLayer.getHeight() - mTaskbarView.getBottom(); - } - - public void onDragLayerViewRemoved() { - if (AbstractFloatingView.getOpenView(mActivity, TYPE_ALL) == null) { - mActivity.setTaskbarWindowFullscreen(false); - } - } - } -} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index 34f66ba6b1..260cedc706 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -15,8 +15,7 @@ */ package com.android.launcher3.taskbar; -import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; -import com.android.quickstep.AnimatedFloat; +import android.graphics.Rect; /** * Base class for providing different taskbar UI @@ -25,12 +24,13 @@ public class TaskbarUIController { public static final TaskbarUIController DEFAULT = new TaskbarUIController(); - protected void init(AnimatedFloat taskBarAlpha, AlphaProperty iconAlphaForLauncherState, - AlphaProperty iconAlphaForHome) { } + protected void init(TaskbarControllers taskbarControllers) { } protected void onDestroy() { } protected boolean isTaskbarTouchable() { return true; } + + protected void updateContentInsets(Rect outContentInsets) { } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index d41550270d..373ca2aebe 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -60,6 +60,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar private final TaskbarActivityContext mActivityContext; // Initialized in init. + private TaskbarViewController.TaskbarViewCallbacks mControllerCallbacks; private View.OnClickListener mIconClickListener; private View.OnLongClickListener mIconLongClickListener; @@ -98,9 +99,10 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar mItemPadding = (mIconTouchSize - actualIconSize) / 2; } - protected void init(OnClickListener clickListener, OnLongClickListener longClickListener) { - mIconClickListener = clickListener; - mIconLongClickListener = longClickListener; + protected void init(TaskbarViewController.TaskbarViewCallbacks callbacks) { + mControllerCallbacks = callbacks; + mIconClickListener = mControllerCallbacks.getOnClickListener(); + mIconLongClickListener = mControllerCallbacks.getOnLongClickListener(); int numHotseatIcons = mActivityContext.getDeviceProfile().numShownHotseatIcons; updateHotseatItems(new ItemInfo[numHotseatIcons]); @@ -200,11 +202,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar && hotseatItemInfo instanceof WorkspaceItemInfo) { ((BubbleTextView) hotseatView).applyFromWorkspaceItem( (WorkspaceItemInfo) hotseatItemInfo); - hotseatView.setOnClickListener(mIconClickListener); - hotseatView.setOnLongClickListener(mIconLongClickListener); + setClickAndLongClickListenersForIcon(hotseatView); } else if (isFolder) { - hotseatView.setOnClickListener(mIconClickListener); - hotseatView.setOnLongClickListener(mIconLongClickListener); + setClickAndLongClickListenersForIcon(hotseatView); } else { hotseatView.setOnClickListener(null); hotseatView.setOnLongClickListener(null); @@ -214,6 +214,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar } } + /** + * Sets OnClickListener and OnLongClickListener for the given view. + */ + public void setClickAndLongClickListenersForIcon(View icon) { + icon.setOnClickListener(mIconClickListener); + icon.setOnLongClickListener(mIconLongClickListener); + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { int count = getChildCount(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java new file mode 100644 index 0000000000..b6184c962b --- /dev/null +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -0,0 +1,85 @@ +/* + * 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.view.View; + +import com.android.launcher3.util.MultiValueAlpha; + +/** + * Handles properties/data collection, then passes the results to TaskbarView to render. + */ +public class TaskbarViewController { + + public static final int ALPHA_INDEX_HOME = 0; + public static final int ALPHA_INDEX_LAUNCHER_STATE = 1; + public static final int ALPHA_INDEX_IME = 2; + + private final TaskbarActivityContext mActivity; + private final TaskbarView mTaskbarView; + private final MultiValueAlpha mTaskbarIconAlpha; + + // Initialized in init. + private TaskbarControllers mControllers; + + public TaskbarViewController(TaskbarActivityContext activity, TaskbarView taskbarView) { + mActivity = activity; + mTaskbarView = taskbarView; + mTaskbarIconAlpha = new MultiValueAlpha(mTaskbarView, 3); + mTaskbarIconAlpha.setUpdateVisibility(true); + } + + public void init(TaskbarControllers controllers) { + mControllers = controllers; + mTaskbarView.init(new TaskbarViewCallbacks()); + mTaskbarView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize; + } + + 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); + } + + /** + * Sets OnClickListener and OnLongClickListener for the given view. + */ + public void setClickAndLongClickListenersForIcon(View icon) { + mTaskbarView.setClickAndLongClickListenersForIcon(icon); + } + + /** + * Callbacks for {@link TaskbarView} to interact with its controller. + */ + public class TaskbarViewCallbacks { + public View.OnClickListener getOnClickListener() { + return mActivity::onTaskbarIconClicked; + } + + public View.OnLongClickListener getOnLongClickListener() { + return mControllers.taskbarDragController::startDragOnLongClick; + } + } +}