Put taskbar all apps in separate overlay window and stash taskbar. am: a1370bfc5f

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/16988304

Change-Id: Idc091c3ad962c754a03d8bfe1eebe8c6a23c304d
This commit is contained in:
Brian Isganitis
2022-02-23 19:33:06 +00:00
committed by Automerger Merge Worker
16 changed files with 596 additions and 182 deletions
+4 -4
View File
@@ -14,12 +14,12 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<com.android.launcher3.taskbar.TaskbarAllAppsSlideInView
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.android.launcher3.taskbar.TaskbarAllAppsContainerView
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
android:id="@+id/apps_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -52,5 +52,5 @@
</com.android.launcher3.allapps.FloatingHeaderView>
<include layout="@layout/all_apps_fast_scroller" />
</com.android.launcher3.taskbar.TaskbarAllAppsContainerView>
</com.android.launcher3.taskbar.TaskbarAllAppsSlideInView>
</com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView>
</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
@@ -0,0 +1,69 @@
/*
* Copyright (C) 2022 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.content.Context;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
import java.util.ArrayList;
import java.util.List;
// TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar.
/** Base for common behavior between taskbar window contexts. */
public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext,
DeviceProfileListenable {
protected final LayoutInflater mLayoutInflater;
private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
protected DeviceProfile mDeviceProfile;
public BaseTaskbarContext(Context windowContext) {
super(windowContext, Themes.getActivityThemeRes(windowContext));
mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
}
@Override
public final LayoutInflater getLayoutInflater() {
return mLayoutInflater;
}
@Override
public final DeviceProfile getDeviceProfile() {
return mDeviceProfile;
}
@Override
public final List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
return mDPChangeListeners;
}
/** Updates the {@link DeviceProfile} instance to the latest representation of the screen. */
public abstract void updateDeviceProfile(DeviceProfile dp);
/** Callback invoked when a drag is initiated within this context. */
public abstract void onDragStart();
/** Callback invoked when a popup is shown or closed within this context. */
public abstract void onPopupVisibilityChanged(boolean isVisible);
}
@@ -42,10 +42,8 @@ import android.os.Process;
import android.os.SystemProperties;
import android.provider.Settings;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.RoundedCorner;
import android.view.View;
import android.view.WindowManager;
@@ -58,11 +56,8 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
@@ -72,11 +67,10 @@ import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.SettingsCache;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.ViewCache;
import com.android.launcher3.views.ActivityContext;
@@ -89,16 +83,13 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
/**
* The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
* that are used by both Launcher and Taskbar (such as Folder) to reference a generic
* ActivityContext and BaseDragLayer instead of the Launcher activity and its DragLayer.
*/
public class TaskbarActivityContext extends ContextThemeWrapper implements ActivityContext,
DeviceProfileListenable {
public class TaskbarActivityContext extends BaseTaskbarContext {
private static final boolean ENABLE_THREE_BUTTON_TASKBAR =
SystemProperties.getBoolean("persist.debug.taskbar_three_button", false);
@@ -106,13 +97,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
private static final String WINDOW_TITLE = "Taskbar";
private final LayoutInflater mLayoutInflater;
private final TaskbarDragLayer mDragLayer;
private final TaskbarAllAppsContainerView mAppsView;
private final TaskbarControllers mControllers;
private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
private DeviceProfile mDeviceProfile;
private final WindowManager mWindowManager;
private final @Nullable RoundedCorner mLeftCorner, mRightCorner;
@@ -135,14 +121,12 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
private boolean mBindingItems = false;
private final TaskbarShortcutMenuAccessibilityDelegate mAccessibilityDelegate;
private final OnboardingPrefs<TaskbarActivityContext> mOnboardingPrefs;
public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
unfoldTransitionProgressProvider) {
super(windowContext, Themes.getActivityThemeRes(windowContext));
super(windowContext);
mDeviceProfile = dp;
mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
mNavMode = SysUINavigationMode.getMode(windowContext);
mImeDrawsImeNavBar = SysUINavigationMode.getImeDrawsImeNavBar(windowContext);
@@ -158,8 +142,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size);
mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
// Inflate views.
mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
R.layout.taskbar, null, false);
@@ -168,11 +150,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
TaskbarAllAppsSlideInView appsSlideInView =
(TaskbarAllAppsSlideInView) mLayoutInflater.inflate(R.layout.taskbar_all_apps,
mDragLayer, false);
mAppsView = appsSlideInView.getAppsView();
Display display = windowContext.getDisplay();
Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
? windowContext.getApplicationContext()
@@ -210,7 +187,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
new TaskbarAutohideSuspendController(this),
new TaskbarPopupController(this),
new TaskbarForceVisibleImmersiveController(this),
new TaskbarAllAppsViewController(this, appsSlideInView));
new TaskbarAllAppsController(this));
}
public void init(TaskbarSharedState sharedState) {
@@ -236,7 +213,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
}
/** Updates the Device profile instance to the latest representation of the screen. */
@Override
public void updateDeviceProfile(DeviceProfile dp) {
mDeviceProfile = dp;
updateIconSize(getResources());
@@ -296,31 +273,11 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
return mRightCorner == null ? 0 : mRightCorner.getRadius();
}
@Override
public LayoutInflater getLayoutInflater() {
return mLayoutInflater;
}
@Override
public TaskbarDragLayer getDragLayer() {
return mDragLayer;
}
@Override
public TaskbarAllAppsContainerView getAppsView() {
return mAppsView;
}
@Override
public DeviceProfile getDeviceProfile() {
return mDeviceProfile;
}
@Override
public List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
return mDPChangeListeners;
}
@Override
public Rect getFolderBoundingBox() {
return mControllers.taskbarDragLayerController.getFolderBoundingBox();
@@ -411,11 +368,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
return mAccessibilityDelegate;
}
@Override
public OnboardingPrefs<TaskbarActivityContext> getOnboardingPrefs() {
return mOnboardingPrefs;
}
@Override
public boolean isBindingItems() {
return mBindingItems;
@@ -425,6 +377,16 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
mBindingItems = bindingItems;
}
@Override
public void onDragStart() {
setTaskbarWindowFullscreen(true);
}
@Override
public void onPopupVisibilityChanged(boolean isVisible) {
setTaskbarWindowFocusable(isVisible);
}
/**
* Sets a new data-source for this taskbar instance
*/
@@ -1,84 +0,0 @@
/*
* Copyright (C) 2022 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.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import com.android.launcher3.appprediction.AppsDividerView;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import java.util.List;
/** Handles the {@link TaskbarAllAppsContainerView} initialization and updates. */
public final class TaskbarAllAppsViewController {
private final TaskbarActivityContext mContext;
private final TaskbarAllAppsSlideInView mSlideInView;
private final TaskbarAllAppsContainerView mAppsView;
public TaskbarAllAppsViewController(
TaskbarActivityContext context, TaskbarAllAppsSlideInView slideInView) {
mContext = context;
mSlideInView = slideInView;
mAppsView = mSlideInView.getAppsView();
}
/** Initialize the controller. */
public void init(TaskbarControllers controllers) {
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
return;
}
mAppsView.setOnIconLongClickListener(
controllers.taskbarDragController::startDragOnLongClick);
mAppsView.getFloatingHeaderView().findFixedRowByType(
PredictionRowView.class).setOnIconLongClickListener(
controllers.taskbarDragController::startDragOnLongClick);
}
/** Binds the current {@link AppInfo} instances to the {@link TaskbarAllAppsContainerView}. */
public void setApps(AppInfo[] apps, int flags) {
if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
mAppsView.getAppsStore().setApps(apps, flags);
}
}
/** Binds the current app predictions to all apps {@link PredictionRowView}. */
public void setPredictedApps(List<ItemInfo> predictedApps) {
if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
PredictionRowView<?> predictionRowView =
mAppsView.getFloatingHeaderView().findFixedRowByType(PredictionRowView.class);
predictionRowView.setPredictedApps(predictedApps);
}
}
/** Opens the {@link TaskbarAllAppsContainerView}. */
public void show() {
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
return;
}
mAppsView.getFloatingHeaderView().findFixedRowByType(AppsDividerView.class)
.setShowAllAppsLabel(
!mContext.getOnboardingPrefs().hasReachedMaxCount(ALL_APPS_VISITED_COUNT));
mContext.getOnboardingPrefs().incrementEventCount(ALL_APPS_VISITED_COUNT);
mContext.setTaskbarWindowFullscreen(true);
mSlideInView.show();
}
}
@@ -20,6 +20,7 @@ import android.content.pm.ActivityInfo.Config;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
import com.android.systemui.shared.rotation.RotationButtonController;
import java.io.PrintWriter;
@@ -48,7 +49,7 @@ public class TaskbarControllers {
public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
public final TaskbarPopupController taskbarPopupController;
public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
public final TaskbarAllAppsViewController taskbarAllAppsViewController;
public final TaskbarAllAppsController taskbarAllAppsController;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@@ -74,7 +75,7 @@ public class TaskbarControllers {
TaskbarAutohideSuspendController taskbarAutoHideSuspendController,
TaskbarPopupController taskbarPopupController,
TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController,
TaskbarAllAppsViewController taskbarAllAppsViewController) {
TaskbarAllAppsController taskbarAllAppsController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -91,7 +92,7 @@ public class TaskbarControllers {
this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
this.taskbarPopupController = taskbarPopupController;
this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
this.taskbarAllAppsViewController = taskbarAllAppsViewController;
this.taskbarAllAppsController = taskbarAllAppsController;
}
/**
@@ -115,7 +116,7 @@ public class TaskbarControllers {
taskbarEduController.init(this);
taskbarPopupController.init(this);
taskbarForceVisibleImmersiveController.init(this);
taskbarAllAppsViewController.init(this);
taskbarAllAppsController.init(this);
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -75,7 +75,7 @@ import java.util.Arrays;
/**
* Handles long click on Taskbar items to start a system drag and drop operation.
*/
public class TaskbarDragController extends DragController<TaskbarActivityContext> implements
public class TaskbarDragController extends DragController<BaseTaskbarContext> implements
TaskbarControllers.LoggableTaskbarController {
private static boolean DEBUG_DRAG_SHADOW_SURFACE = false;
@@ -95,7 +95,7 @@ public class TaskbarDragController extends DragController<TaskbarActivityContext
// Animation for the drag shadow back into position after an unsuccessful drag
private ValueAnimator mReturnAnimator;
public TaskbarDragController(TaskbarActivityContext activity) {
public TaskbarDragController(BaseTaskbarContext activity) {
super(activity);
Resources resources = mActivity.getResources();
mDragIconSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_drag_icon_size);
@@ -110,7 +110,7 @@ public class TaskbarDragController extends DragController<TaskbarActivityContext
* generate the ClipDescription and Intent.
* @return Whether {@link View#startDragAndDrop} started successfully.
*/
protected boolean startDragOnLongClick(View view) {
public boolean startDragOnLongClick(View view) {
return startDragOnLongClick(view, null, null);
}
@@ -131,8 +131,7 @@ public class TaskbarDragController extends DragController<TaskbarActivityContext
}
BubbleTextView btv = (BubbleTextView) view;
mActivity.setTaskbarWindowFullscreen(true);
mActivity.onDragStart();
btv.post(() -> {
DragView dragView = startInternalDrag(btv, dragPreviewProvider);
if (iconShift != null) {
@@ -185,7 +184,7 @@ public class TaskbarDragController extends DragController<TaskbarActivityContext
}
};
if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
PopupContainerWithArrow<TaskbarActivityContext> popupContainer =
PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
mControllers.taskbarPopupController.showForIcon(btv);
if (popupContainer != null) {
dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
@@ -25,8 +25,8 @@ import com.android.launcher3.dragndrop.DragView;
* while the pre-drag is still in progress (i.e. when the long press popup is still open). After
* that ends, we switch to a system drag and drop view instead.
*/
public class TaskbarDragView extends DragView<TaskbarActivityContext> {
public TaskbarDragView(TaskbarActivityContext launcher, Drawable drawable, int registrationX,
public class TaskbarDragView extends DragView<BaseTaskbarContext> {
public TaskbarDragView(BaseTaskbarContext launcher, Drawable drawable, int registrationX,
int registrationY, float initialScale, float scaleOnDrop, float finalScaleDps) {
super(launcher, drawable, registrationX, registrationY, initialScale, scaleOnDrop,
finalScaleDps);
@@ -158,7 +158,7 @@ public class TaskbarModelCallbacks implements
mPredictedItems = item.items;
commitItemsToUI();
} else if (item.containerId == Favorites.CONTAINER_PREDICTION) {
mControllers.taskbarAllAppsViewController.setPredictedApps(item.items);
mControllers.taskbarAllAppsController.setPredictedApps(item.items);
}
}
@@ -201,7 +201,7 @@ public class TaskbarModelCallbacks implements
@Override
public void bindAllApplications(AppInfo[] apps, int flags) {
mControllers.taskbarAllAppsViewController.setApps(apps, flags);
mControllers.taskbarAllAppsController.setApps(apps, flags);
}
protected void dumpLogs(String prefix, PrintWriter pw) {
@@ -52,7 +52,7 @@ import java.util.stream.Stream;
*/
public class TaskbarPopupController implements TaskbarControllers.LoggableTaskbarController {
private static final SystemShortcut.Factory<TaskbarActivityContext>
private static final SystemShortcut.Factory<BaseTaskbarContext>
APP_INFO = SystemShortcut.AppInfo::new;
private final TaskbarActivityContext mContext;
@@ -121,8 +121,8 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
* Shows the notifications and deep shortcuts associated with a Taskbar {@param icon}.
* @return the container if shown or null.
*/
public PopupContainerWithArrow<TaskbarActivityContext> showForIcon(BubbleTextView icon) {
TaskbarActivityContext context = ActivityContext.lookupContext(icon.getContext());
public PopupContainerWithArrow<BaseTaskbarContext> showForIcon(BubbleTextView icon) {
BaseTaskbarContext context = ActivityContext.lookupContext(icon.getContext());
if (PopupContainerWithArrow.getOpen(context) != null) {
// There is already an items container open, so don't open this one.
icon.clearFocus();
@@ -133,11 +133,11 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
return null;
}
final PopupContainerWithArrow<TaskbarActivityContext> container =
(PopupContainerWithArrow) context.getLayoutInflater().inflate(
final PopupContainerWithArrow<BaseTaskbarContext> container =
(PopupContainerWithArrow<BaseTaskbarContext>) context.getLayoutInflater().inflate(
R.layout.popup_container, context.getDragLayer(), false);
container.addOnAttachStateChangeListener(
new PopupLiveUpdateHandler<TaskbarActivityContext>(mContext, container) {
new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
@Override
protected void showPopupContainerForIcon(BubbleTextView originalIcon) {
showForIcon(originalIcon);
@@ -157,10 +157,9 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
container.requestFocus();
// Make focusable to receive back events
mControllers.taskbarActivityContext.setTaskbarWindowFocusable(true);
context.onPopupVisibilityChanged(true);
container.setOnCloseCallback(() -> {
mControllers.taskbarActivityContext.getDragLayer().post(
() -> mControllers.taskbarActivityContext.setTaskbarWindowFocusable(false));
context.getDragLayer().post(() -> context.onPopupVisibilityChanged(false));
container.setOnCloseCallback(null);
});
@@ -207,7 +206,8 @@ public class TaskbarPopupController implements TaskbarControllers.LoggableTaskba
iconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x;
iconShift.y = mIconLastTouchPos.y - mContext.getDeviceProfile().iconSizePx;
mControllers.taskbarDragController.startDragOnLongClick(sv, iconShift);
((TaskbarDragController) ActivityContext.lookupContext(
v.getContext()).getDragController()).startDragOnLongClick(sv, iconShift);
return false;
}
@@ -51,11 +51,12 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
public static final int FLAG_STASHED_IN_APP_ALL_APPS = 1 << 7; // All apps is visible.
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
| FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
| FLAG_STASHED_IN_APP_IME;
| FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_APP_ALL_APPS;
// If any of these flags are enabled, inset apps by our stashed height instead of our unstashed
// height. This way the reported insets are consistent even during transitions out of the app.
@@ -585,6 +586,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
str.add((flags & FLAG_STASHED_IN_APP_IME) != 0 ? "FLAG_STASHED_IN_APP_IME" : "");
str.add((flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0
? "FLAG_IN_STASHED_LAUNCHER_STATE" : "");
str.add((flags & FLAG_STASHED_IN_APP_ALL_APPS) != 0 ? "FLAG_STASHED_IN_APP_ALL_APPS" : "");
return str.toString();
}
@@ -306,7 +306,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
}
public View.OnClickListener getAllAppsButtonClickListener() {
return v -> mControllers.taskbarAllAppsViewController.show();
return v -> mControllers.taskbarAllAppsController.show();
}
public View.OnLongClickListener getIconOnLongClickListener() {
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.taskbar;
package com.android.launcher3.taskbar.allapps;
import android.content.Context;
import android.util.AttributeSet;
@@ -29,10 +29,7 @@ import com.android.launcher3.allapps.BaseAllAppsContainerView;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
/** All apps container accessible from taskbar. */
public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<TaskbarActivityContext> {
public TaskbarAllAppsContainerView(Context context) {
this(context, null);
}
public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<TaskbarAllAppsContext> {
public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -44,8 +41,8 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<Taskba
@Override
protected SearchAdapterProvider<?> createMainAdapterProvider() {
// Task bar all apps does not yet support search, so this implementation is minimal.
return new SearchAdapterProvider<TaskbarActivityContext>(mActivityContext) {
// Taskbar all apps does not yet support search, so this implementation is minimal.
return new SearchAdapterProvider<TaskbarAllAppsContext>(mActivityContext) {
@Override
public boolean launchHighlightedItem() {
return false;
@@ -79,8 +76,7 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<Taskba
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
// TODO(b/204696617): Switch to status bar insets once they work.
setInsets(insets.getInsets(WindowInsets.Type.tappableElement()).toRect());
setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
return super.onApplyWindowInsets(insets);
}
}
@@ -0,0 +1,164 @@
/*
* Copyright (C) 2022 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.allapps;
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_BACK;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.content.Context;
import android.view.KeyEvent;
import android.view.View;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dot.DotInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.taskbar.BaseTaskbarContext;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarDragController;
import com.android.launcher3.taskbar.TaskbarStashController;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
/**
* Window context for the taskbar all apps overlay.
* <p>
* All apps has its own window and needs a window context. Some properties are delegated to the
* {@link TaskbarActivityContext} such as {@link DeviceProfile} and {@link PopupDataProvider}.
*/
class TaskbarAllAppsContext extends BaseTaskbarContext {
private final TaskbarActivityContext mTaskbarContext;
private final OnboardingPrefs<TaskbarAllAppsContext> mOnboardingPrefs;
private final TaskbarAllAppsViewController mAllAppsViewController;
private final TaskbarDragController mDragController;
private final TaskbarAllAppsDragLayer mDragLayer;
private final TaskbarAllAppsContainerView mAppsView;
TaskbarAllAppsContext(
TaskbarActivityContext taskbarContext,
TaskbarAllAppsController windowController,
TaskbarStashController taskbarStashController) {
super(taskbarContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null));
mTaskbarContext = taskbarContext;
mDeviceProfile = taskbarContext.getDeviceProfile();
mDragController = new TaskbarDragController(this);
mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
mDragLayer = new TaskbarAllAppsDragLayer(this);
TaskbarAllAppsSlideInView slideInView = (TaskbarAllAppsSlideInView) mLayoutInflater.inflate(
R.layout.taskbar_all_apps, mDragLayer, false);
mAllAppsViewController = new TaskbarAllAppsViewController(
this,
slideInView,
windowController,
taskbarStashController);
mAppsView = slideInView.getAppsView();
}
TaskbarAllAppsViewController getAllAppsViewController() {
return mAllAppsViewController;
}
@Override
public TaskbarDragController getDragController() {
return mDragController;
}
@Override
public TaskbarAllAppsDragLayer getDragLayer() {
return mDragLayer;
}
@Override
public TaskbarAllAppsContainerView getAppsView() {
return mAppsView;
}
@Override
public OnboardingPrefs<TaskbarAllAppsContext> getOnboardingPrefs() {
return mOnboardingPrefs;
}
@Override
public boolean isBindingItems() {
return mTaskbarContext.isBindingItems();
}
@Override
public View.OnClickListener getItemOnClickListener() {
return mTaskbarContext.getItemOnClickListener();
}
@Override
public PopupDataProvider getPopupDataProvider() {
return mTaskbarContext.getPopupDataProvider();
}
@Override
public DotInfo getDotInfoForItem(ItemInfo info) {
return mTaskbarContext.getDotInfoForItem(info);
}
@Override
public void updateDeviceProfile(DeviceProfile dp) {
mDeviceProfile = dp;
dispatchDeviceProfileChanged();
}
@Override
public void onDragStart() {}
@Override
public void onPopupVisibilityChanged(boolean isVisible) {}
/** Root drag layer for this context. */
private static class TaskbarAllAppsDragLayer extends BaseDragLayer<TaskbarAllAppsContext> {
private TaskbarAllAppsDragLayer(Context context) {
super(context, null, 1);
setClipChildren(false);
recreateControllers();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mActivity.mAllAppsViewController.show();
}
@Override
public void recreateControllers() {
mControllers = new TouchController[]{mActivity.mDragController};
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
if (topView != null && topView.onBackPressed()) {
return true;
}
}
return super.dispatchKeyEvent(event);
}
}
}
@@ -0,0 +1,199 @@
/*
* Copyright (C) 2022 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.allapps;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarControllers;
import java.util.List;
import java.util.Optional;
/**
* Handles the all apps overlay window initialization, updates, and its data.
* <p>
* All apps is in an application overlay window instead of taskbar's navigation bar panel window,
* because a navigation bar panel is higher than UI components that all apps should be below such as
* the notification tray.
* <p>
* The all apps window is created and destroyed upon opening and closing all apps, respectively.
* Application data may be bound while the window does not exist, so this controller will store
* the models for the next all apps session.
*/
public final class TaskbarAllAppsController implements OnDeviceProfileChangeListener {
private static final String WINDOW_TITLE = "Taskbar All Apps";
private final TaskbarActivityContext mTaskbarContext;
private final TaskbarAllAppsProxyView mProxyView;
private final LayoutParams mLayoutParams;
private TaskbarControllers mControllers;
/** Window context for all apps if it is open. */
private @Nullable TaskbarAllAppsContext mAllAppsContext;
// Application data models.
private AppInfo[] mApps;
private int mAppsModelFlags;
private List<ItemInfo> mPredictedApps;
public TaskbarAllAppsController(TaskbarActivityContext context) {
mTaskbarContext = context;
mProxyView = new TaskbarAllAppsProxyView(mTaskbarContext);
mLayoutParams = createLayoutParams();
}
/** Initialize the controller. */
public void init(TaskbarControllers controllers) {
if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
mControllers = controllers;
}
}
/** Updates the current {@link AppInfo} instances. */
public void setApps(AppInfo[] apps, int flags) {
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
return;
}
mApps = apps;
mAppsModelFlags = flags;
if (mAllAppsContext != null) {
mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags);
}
}
/** Updates the current predictions. */
public void setPredictedApps(List<ItemInfo> predictedApps) {
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
return;
}
mPredictedApps = predictedApps;
if (mAllAppsContext != null) {
mAllAppsContext.getAppsView().getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class)
.setPredictedApps(mPredictedApps);
}
}
/** Opens the {@link TaskbarAllAppsContainerView} in a new window. */
public void show() {
if (mProxyView.isOpen()) {
return;
}
mProxyView.show();
mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext,
this,
mControllers.taskbarStashController);
mAllAppsContext.getDragController().init(mControllers);
mTaskbarContext.addOnDeviceProfileChangeListener(this);
Optional.ofNullable(mAllAppsContext.getSystemService(WindowManager.class))
.ifPresent(m -> m.addView(mAllAppsContext.getDragLayer(), mLayoutParams));
mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags);
mAllAppsContext.getAppsView().getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class)
.setPredictedApps(mPredictedApps);
}
/**
* Removes the all apps window from the hierarchy.
* <p>
* This method should be called after an exit animation finishes, if applicable.
*/
void closeWindow() {
mProxyView.close(false);
mTaskbarContext.removeOnDeviceProfileChangeListener(this);
Optional.ofNullable(mAllAppsContext)
.map(c -> c.getSystemService(WindowManager.class))
.ifPresent(m -> m.removeView(mAllAppsContext.getDragLayer()));
mAllAppsContext = null;
}
private LayoutParams createLayoutParams() {
LayoutParams layoutParams = new LayoutParams(
TYPE_APPLICATION_OVERLAY,
0,
PixelFormat.TRANSLUCENT);
layoutParams.setTitle(WINDOW_TITLE);
layoutParams.gravity = Gravity.BOTTOM;
layoutParams.packageName = mTaskbarContext.getPackageName();
layoutParams.setFitInsetsTypes(0); // Handled by container view.
layoutParams.setSystemApplicationOverlay(true);
return layoutParams;
}
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
Optional.ofNullable(mAllAppsContext).ifPresent(c -> c.updateDeviceProfile(dp));
}
/**
* Proxy view connecting taskbar drag layer to the all apps window.
* <p>
* The all apps view is in a separate window and has its own drag layer, but this proxy lets it
* behave as though its in the taskbar drag layer. For instance, when the taskbar closes all
* {@link AbstractFloatingView} instances, the all apps window will also close.
*/
private class TaskbarAllAppsProxyView extends AbstractFloatingView {
private TaskbarAllAppsProxyView(Context context) {
super(context, null);
}
private void show() {
mIsOpen = true;
mTaskbarContext.getDragLayer().addView(this);
}
@Override
protected void handleClose(boolean animate) {
mTaskbarContext.getDragLayer().removeView(this);
Optional.ofNullable(mAllAppsContext)
.map(TaskbarAllAppsContext::getAllAppsViewController)
.ifPresent(v -> v.close(animate));
}
@Override
protected boolean isOfType(int type) {
return (type & TYPE_TASKBAR_ALL_APPS) != 0;
}
@Override
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
return false;
}
}
}
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.taskbar;
package com.android.launcher3.taskbar.allapps;
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
@@ -27,14 +27,17 @@ import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.views.AbstractSlideInView;
import java.util.Optional;
/** Wrapper for taskbar all apps with slide-in behavior. */
public class TaskbarAllAppsSlideInView extends
AbstractSlideInView<TaskbarActivityContext> implements Insettable {
AbstractSlideInView<TaskbarAllAppsContext> implements Insettable {
private static final int DEFAULT_OPEN_DURATION = 500;
private static final int DEFAULT_CLOSE_DURATION = 200;
static final int DEFAULT_OPEN_DURATION = 500;
static final int DEFAULT_CLOSE_DURATION = 200;
private TaskbarAllAppsContainerView mAppsView;
private OnCloseListener mOnCloseBeginListener;
public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -46,7 +49,7 @@ public class TaskbarAllAppsSlideInView extends
}
/** Opens the all apps view. */
public void show() {
void show() {
if (mIsOpen || mOpenCloseAnimator.isRunning()) {
return;
}
@@ -60,12 +63,18 @@ public class TaskbarAllAppsSlideInView extends
}
/** The apps container inside this view. */
public TaskbarAllAppsContainerView getAppsView() {
TaskbarAllAppsContainerView getAppsView() {
return mAppsView;
}
/** Callback invoked when the view is beginning to close (e.g. close animation is started). */
void setOnCloseBeginListener(OnCloseListener onCloseBeginListener) {
mOnCloseBeginListener = onCloseBeginListener;
}
@Override
protected void handleClose(boolean animate) {
Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
handleClose(animate, DEFAULT_CLOSE_DURATION);
}
@@ -81,6 +90,12 @@ public class TaskbarAllAppsSlideInView extends
mContent = mAppsView;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
setTranslationShift(mTranslationShift);
}
@Override
protected int getScrimColor(Context context) {
return context.getColor(R.color.widgets_picker_scrim);
@@ -0,0 +1,91 @@
/*
* Copyright (C) 2022 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.allapps;
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_ALL_APPS;
import static com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView.DEFAULT_CLOSE_DURATION;
import static com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView.DEFAULT_OPEN_DURATION;
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
import com.android.launcher3.appprediction.AppsDividerView;
import com.android.launcher3.appprediction.PredictionRowView;
import com.android.launcher3.taskbar.TaskbarStashController;
/**
* Handles the {@link TaskbarAllAppsContainerView} behavior and synchronizes its transitions with
* taskbar stashing.
*/
final class TaskbarAllAppsViewController {
private final TaskbarAllAppsContext mContext;
private final TaskbarAllAppsSlideInView mSlideInView;
private final TaskbarAllAppsContainerView mAppsView;
private final TaskbarStashController mTaskbarStashController;
TaskbarAllAppsViewController(
TaskbarAllAppsContext context,
TaskbarAllAppsSlideInView slideInView,
TaskbarAllAppsController windowController,
TaskbarStashController taskbarStashController) {
mContext = context;
mSlideInView = slideInView;
mAppsView = mSlideInView.getAppsView();
mTaskbarStashController = taskbarStashController;
setUpIconLongClick();
setUpAppDivider();
setUpTaskbarStashing();
mSlideInView.addOnCloseListener(windowController::closeWindow);
}
/** Starts the {@link TaskbarAllAppsSlideInView} enter transition. */
void show() {
mSlideInView.show();
}
/** Closes the {@link TaskbarAllAppsSlideInView}. */
void close(boolean animate) {
mSlideInView.close(animate);
}
private void setUpIconLongClick() {
mAppsView.setOnIconLongClickListener(
mContext.getDragController()::startDragOnLongClick);
mAppsView.getFloatingHeaderView()
.findFixedRowByType(PredictionRowView.class)
.setOnIconLongClickListener(
mContext.getDragController()::startDragOnLongClick);
}
private void setUpAppDivider() {
mAppsView.getFloatingHeaderView()
.findFixedRowByType(AppsDividerView.class)
.setShowAllAppsLabel(!mContext.getOnboardingPrefs().hasReachedMaxCount(
ALL_APPS_VISITED_COUNT));
mContext.getOnboardingPrefs().incrementEventCount(ALL_APPS_VISITED_COUNT);
}
private void setUpTaskbarStashing() {
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, true);
mTaskbarStashController.applyState(DEFAULT_OPEN_DURATION);
mSlideInView.setOnCloseBeginListener(() -> {
mTaskbarStashController.updateStateForFlag(
FLAG_STASHED_IN_APP_ALL_APPS, false);
mTaskbarStashController.applyState(DEFAULT_CLOSE_DURATION);
});
}
}