Merge "Adjust where the back button is rendered for new SUW requirements." into 24D1-dev
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 4462f20..2730be1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -118,7 +118,7 @@
FolderInfo fi = (FolderInfo) info;
if (fi.anyMatch(matcher)) {
FolderDotInfo folderDotInfo = new FolderDotInfo();
- for (WorkspaceItemInfo si : fi.getContents()) {
+ for (ItemInfo si : fi.getContents()) {
folderDotInfo.addDotInfo(mPopupDataProvider.getDotInfoForItem(si));
}
((FolderIcon) v).setDotInfo(folderDotInfo);
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index cc582d1..2fa3001 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -82,9 +82,10 @@
boolean isTablet = activity.getDeviceProfile().isTablet;
boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview();
- // Add overview actions to the menu when in in-place rotate landscape mode, or in
- // grid-only overview.
- if ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview) {
+ // Add overview actions to the menu when:
+ // - single task is showing
+ // - in in-place rotate landscape mode, or in grid-only overview.
+ if (!hasMultipleTasks && ((!canLauncherRotate && isInLandscape) || isGridOnlyOverview)) {
// Add screenshot action to task menu.
List<SystemShortcut> screenshotShortcuts = TaskShortcutFactory.SCREENSHOT
.getShortcuts(activity, taskContainer);
diff --git a/quickstep/src/com/android/quickstep/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index f4da867..3ed3e40 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -45,7 +45,6 @@
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherSettings;
-import com.android.launcher3.R;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsStore;
import com.android.launcher3.apppairs.AppPairIcon;
@@ -153,13 +152,11 @@
IconCache iconCache = LauncherAppState.getInstance(mContext).getIconCache();
MODEL_EXECUTOR.execute(() -> {
- newAppPair.getContents().forEach(member -> {
+ newAppPair.getAppContents().forEach(member -> {
member.title = "";
member.bitmap = iconCache.getDefaultIcon(newAppPair.user);
iconCache.getTitleAndIcon(member, member.usingLowResIcon());
});
- newAppPair.title = getDefaultTitle(newAppPair.getFirstApp().title,
- newAppPair.getSecondApp().title);
MAIN_EXECUTOR.execute(() -> {
LauncherAccessibilityDelegate delegate =
Launcher.getLauncher(mContext).getAccessibilityDelegate();
@@ -489,13 +486,6 @@
}
/**
- * Returns a formatted default title for the app pair.
- */
- public String getDefaultTitle(CharSequence app1, CharSequence app2) {
- return mContext.getString(R.string.app_pair_default_title, app1, app2);
- }
-
- /**
* Gets the TopTaskTracker, which is a cached record of the top running Task.
*/
@VisibleForTesting
diff --git a/quickstep/src/com/android/quickstep/util/AssistStateManager.java b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
index 8e071ab..a854656 100644
--- a/quickstep/src/com/android/quickstep/util/AssistStateManager.java
+++ b/quickstep/src/com/android/quickstep/util/AssistStateManager.java
@@ -52,11 +52,6 @@
return Optional.empty();
}
- /** Whether search recovery is available. */
- public boolean isVisRecoveryEnabled() {
- return false;
- }
-
/** Return {@code true} if the Settings toggle is enabled. */
public boolean isSettingsAllEntrypointsEnabled() {
return false;
diff --git a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
index 6b27004..a2d3859 100644
--- a/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
+++ b/quickstep/src/com/android/quickstep/util/SplitAnimationController.kt
@@ -671,6 +671,7 @@
appIcon2,
dividerPos
)
+ floatingView.bringToFront()
// Launcher animation: animate the floating view, expanding to fill the display surface
progressUpdater.addUpdateListener(
diff --git a/res/color-night-v31/material_color_surface_container_high.xml b/res/color-night-v31/material_color_surface_container_high.xml
index 002b88e..edd36fc 100644
--- a/res/color-night-v31/material_color_surface_container_high.xml
+++ b/res/color-night-v31/material_color_surface_container_high.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="17" />
</selector>
\ No newline at end of file
diff --git a/res/color-night-v31/material_color_surface_container_highest.xml b/res/color-night-v31/material_color_surface_container_highest.xml
index 002b88e..e54f953 100644
--- a/res/color-night-v31/material_color_surface_container_highest.xml
+++ b/res/color-night-v31/material_color_surface_container_highest.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="22" />
</selector>
\ No newline at end of file
diff --git a/res/color-night-v31/material_color_surface_container_low.xml b/res/color-night-v31/material_color_surface_container_low.xml
index 002b88e..40f0d4c 100644
--- a/res/color-night-v31/material_color_surface_container_low.xml
+++ b/res/color-night-v31/material_color_surface_container_low.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="10" />
</selector>
\ No newline at end of file
diff --git a/res/color-night-v31/material_color_surface_container_lowest.xml b/res/color-night-v31/material_color_surface_container_lowest.xml
index 002b88e..24f559b 100644
--- a/res/color-night-v31/material_color_surface_container_lowest.xml
+++ b/res/color-night-v31/material_color_surface_container_lowest.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="12" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="4" />
</selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_high.xml b/res/color-v31/material_color_surface_container_high.xml
index b031c08..a996d51 100644
--- a/res/color-v31/material_color_surface_container_high.xml
+++ b/res/color-v31/material_color_surface_container_high.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="92" />
</selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_highest.xml b/res/color-v31/material_color_surface_container_highest.xml
index b031c08..e7a535a 100644
--- a/res/color-v31/material_color_surface_container_highest.xml
+++ b/res/color-v31/material_color_surface_container_highest.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="90" />
</selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_low.xml b/res/color-v31/material_color_surface_container_low.xml
index b031c08..b8fe01e 100644
--- a/res/color-v31/material_color_surface_container_low.xml
+++ b/res/color-v31/material_color_surface_container_low.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="96" />
</selector>
\ No newline at end of file
diff --git a/res/color-v31/material_color_surface_container_lowest.xml b/res/color-v31/material_color_surface_container_lowest.xml
index 674fc73..25e8666 100644
--- a/res/color-v31/material_color_surface_container_lowest.xml
+++ b/res/color-v31/material_color_surface_container_lowest.xml
@@ -15,5 +15,5 @@
~ limitations under the License.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral1_500" android:lStar="94" />
+ <item android:color="@android:color/system_neutral1_500" android:lStar="100" />
</selector>
\ No newline at end of file
diff --git a/res/layout/folder_app_pair.xml b/res/layout/folder_app_pair.xml
new file mode 100644
index 0000000..acecd46
--- /dev/null
+++ b/res/layout/folder_app_pair.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<com.android.launcher3.apppairs.AppPairIcon
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:focusable="true"
+ launcher:iconDisplay="folder" >
+ <com.android.launcher3.apppairs.AppPairIconGraphic
+ android:id="@+id/app_pair_icon_graphic"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="false" />
+ <com.android.launcher3.BubbleTextView
+ style="@style/BaseIcon"
+ android:id="@+id/app_pair_icon_name"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="false"
+ android:layout_gravity="top"
+ android:textColor="?attr/folderTextColor"
+ launcher:iconDisplay="folder" />
+</com.android.launcher3.apppairs.AppPairIcon>
\ No newline at end of file
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 4a0b5e8..b09903d 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -51,6 +51,7 @@
<attr name="folderIconBorderColor" format="color" />
<attr name="folderTextColor" format="color" />
<attr name="folderHintTextColor" format="color" />
+ <attr name="appPairSurfaceInFolder" format="color" />
<attr name="isFolderDarkText" format="boolean" />
<attr name="workspaceAccentColor" format="color" />
<attr name="workspaceSurfaceColor" format="color" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index aaef15b..9f4d308 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -50,6 +50,8 @@
<string name="app_pair_unlaunchable_at_screen_size">This app pair isn\'t supported on this device</string>
<!-- Displayed when an app pair can't launch at this screen size, but user can unfold device to restore functionality [CHAR_LIMIT=none] -->
<string name="app_pair_needs_unfold">Unfold device to use this app pair</string>
+ <!-- Displayed when user selects a shortcut for an app pair that is currently not available [CHAR_LIMIT=none]-->
+ <string name="app_pair_not_available">App pair isn\'t available</string>
<!-- Widgets -->
<!-- Message to tell the user to press and hold on a widget to add it [CHAR_LIMIT=50] -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 401155d..e525369 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -60,6 +60,7 @@
<item name="isFolderDarkText">true</item>
<item name="folderTextColor">@color/folder_text_color_light</item>
<item name="folderHintTextColor">@color/folder_hint_text_color_light</item>
+ <item name="appPairSurfaceInFolder">@color/material_color_surface_container_lowest</item>
<item name="loadingIconColor">#CCFFFFFF</item>
<item name="iconOnlyShortcutColor">?android:attr/textColorSecondary</item>
<item name="eduHalfSheetBGColor">?android:attr/colorAccent</item>
@@ -171,6 +172,7 @@
<item name="isFolderDarkText">false</item>
<item name="folderTextColor">@color/folder_text_color_dark</item>
<item name="folderHintTextColor">@color/folder_hint_text_color_dark</item>
+ <item name="appPairSurfaceInFolder">@color/material_color_surface_container_lowest</item>
<item name="isMainColorDark">true</item>
<item name="loadingIconColor">#99FFFFFF</item>
<item name="iconOnlyShortcutColor">#B3FFFFFF</item>
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index ce3c55a..0fc3211 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -16,8 +16,9 @@
package com.android.launcher3;
+import static com.android.launcher3.BubbleTextView.DISPLAY_FOLDER;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
-import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.EDIT_MODE;
import static com.android.launcher3.LauncherState.FLAG_MULTI_PAGE;
@@ -73,6 +74,7 @@
import com.android.launcher3.accessibility.AccessibleDragListenerAdapter;
import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper;
import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.celllayout.CellInfo;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.celllayout.CellPosMapper;
@@ -241,6 +243,8 @@
public static final int REORDER_TIMEOUT = 650;
protected final Alarm mReorderAlarm = new Alarm();
private PreviewBackground mFolderCreateBg;
+ /** The underlying view that we are dragging something over. */
+ private View mDragOverView = null;
private FolderIcon mDragOverFolderIcon = null;
private boolean mCreateUserFolderOnDrop = false;
private boolean mAddToExistingFolderOnDrop = false;
@@ -1873,12 +1877,9 @@
return false;
}
- boolean aboveShortcut = (dropOverView.getTag() instanceof WorkspaceItemInfo
- && ((WorkspaceItemInfo) dropOverView.getTag()).container
- != LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION);
- boolean willBecomeShortcut =
- (info.itemType == ITEM_TYPE_APPLICATION ||
- info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);
+ boolean aboveShortcut = Folder.willAccept(dropOverView.getTag())
+ && ((ItemInfo) dropOverView.getTag()).container != CONTAINER_HOTSEAT_PREDICTION;
+ boolean willBecomeShortcut = Folder.willAcceptItemType(info.itemType);
return (aboveShortcut && willBecomeShortcut);
}
@@ -1925,12 +1926,12 @@
mCreateUserFolderOnDrop = false;
final int screenId = getCellLayoutId(target);
- boolean aboveShortcut = (v.getTag() instanceof WorkspaceItemInfo);
- boolean willBecomeShortcut = (newView.getTag() instanceof WorkspaceItemInfo);
+ boolean aboveShortcut = Folder.willAccept(v.getTag());
+ boolean willBecomeShortcut = Folder.willAccept(newView.getTag());
if (aboveShortcut && willBecomeShortcut) {
- WorkspaceItemInfo sourceInfo = (WorkspaceItemInfo) newView.getTag();
- WorkspaceItemInfo destInfo = (WorkspaceItemInfo) v.getTag();
+ ItemInfo sourceInfo = (ItemInfo) newView.getTag();
+ ItemInfo destInfo = (ItemInfo) v.getTag();
// if the drag started here, we need to remove it from the workspace
if (!external) {
getParentCellLayoutForView(mDragInfo.cell).removeView(mDragInfo.cell);
@@ -2384,6 +2385,11 @@
if (mFolderCreateBg != null) {
mFolderCreateBg.animateToRest();
}
+
+ if (mDragOverView instanceof AppPairIcon api) {
+ api.getIconDrawableArea().onTemporaryContainerChange(null);
+ mDragOverView = null;
+ }
}
private void cleanupAddToFolder() {
@@ -2659,32 +2665,36 @@
return;
}
- final View dragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
+ mDragOverView = mDragTargetLayout.getChildAt(mTargetCell[0], mTargetCell[1]);
ItemInfo info = dragObject.dragInfo;
- boolean userFolderPending = willCreateUserFolder(info, dragOverView, false);
+ boolean userFolderPending = willCreateUserFolder(info, mDragOverView, false);
if (mDragMode == DRAG_MODE_NONE && userFolderPending) {
mFolderCreateBg = new PreviewBackground();
mFolderCreateBg.setup(mLauncher, mLauncher, null,
- dragOverView.getMeasuredWidth(), dragOverView.getPaddingTop());
+ mDragOverView.getMeasuredWidth(), mDragOverView.getPaddingTop());
// The full preview background should appear behind the icon
mFolderCreateBg.isClipping = false;
+ if (mDragOverView instanceof AppPairIcon api) {
+ api.getIconDrawableArea().onTemporaryContainerChange(DISPLAY_FOLDER);
+ }
+
mFolderCreateBg.animateToAccept(mDragTargetLayout, mTargetCell[0], mTargetCell[1]);
mDragTargetLayout.clearDragOutlines();
setDragMode(DRAG_MODE_CREATE_FOLDER);
if (dragObject.stateAnnouncer != null) {
dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
- .getDescriptionForDropOver(dragOverView, getContext()));
+ .getDescriptionForDropOver(mDragOverView, getContext()));
}
return;
}
- boolean willAddToFolder = willAddToExistingUserFolder(info, dragOverView);
+ boolean willAddToFolder = willAddToExistingUserFolder(info, mDragOverView);
if (willAddToFolder && mDragMode == DRAG_MODE_NONE) {
- mDragOverFolderIcon = ((FolderIcon) dragOverView);
+ mDragOverFolderIcon = ((FolderIcon) mDragOverView);
mDragOverFolderIcon.onDragEnter(info);
if (mDragTargetLayout != null) {
mDragTargetLayout.clearDragOutlines();
@@ -2693,7 +2703,7 @@
if (dragObject.stateAnnouncer != null) {
dragObject.stateAnnouncer.announce(WorkspaceAccessibilityHelper
- .getDescriptionForDropOver(dragOverView, getContext()));
+ .getDescriptionForDropOver(mDragOverView, getContext()));
}
return;
}
@@ -3314,7 +3324,7 @@
}
} else if (child instanceof FolderIcon) {
FolderInfo folderInfo = (FolderInfo) info;
- List<WorkspaceItemInfo> matches = folderInfo.getContents().stream()
+ List<ItemInfo> matches = folderInfo.getContents().stream()
.filter(matcher)
.collect(Collectors.toList());
if (!matches.isEmpty()) {
@@ -3381,7 +3391,7 @@
FolderInfo fi = (FolderInfo) info;
if (fi.anyMatch(matcher)) {
FolderDotInfo folderDotInfo = new FolderDotInfo();
- for (WorkspaceItemInfo si : fi.getContents()) {
+ for (ItemInfo si : fi.getContents()) {
folderDotInfo.addDotInfo(mLauncher.getDotInfoForItem(si));
}
((FolderIcon) v).setDotInfo(folderDotInfo);
diff --git a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
index 52073cc..84d6a6f 100644
--- a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
+++ b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java
@@ -23,6 +23,7 @@
import com.android.launcher3.CellLayout;
import com.android.launcher3.R;
import com.android.launcher3.accessibility.BaseAccessibilityDelegate.DragType;
+import com.android.launcher3.folder.Folder;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -117,7 +118,7 @@
return mContext.getString(R.string.item_moved);
} else {
ItemInfo info = (ItemInfo) child.getTag();
- if (info instanceof AppInfo || info instanceof WorkspaceItemInfo) {
+ if (Folder.willAccept(info)) {
return mContext.getString(R.string.folder_created);
} else if (info instanceof FolderInfo) {
@@ -148,8 +149,8 @@
if (TextUtils.isEmpty(info.title)) {
// Find the first item in the folder.
FolderInfo folder = (FolderInfo) info;
- WorkspaceItemInfo firstItem = null;
- for (WorkspaceItemInfo shortcut : folder.getContents()) {
+ ItemInfo firstItem = null;
+ for (ItemInfo shortcut : folder.getContents()) {
if (firstItem == null || firstItem.rank > shortcut.rank) {
firstItem = shortcut;
}
diff --git a/src/com/android/launcher3/apppairs/AppPairIcon.java b/src/com/android/launcher3/apppairs/AppPairIcon.java
index 9010f82..0e955ad 100644
--- a/src/com/android/launcher3/apppairs/AppPairIcon.java
+++ b/src/com/android/launcher3/apppairs/AppPairIcon.java
@@ -30,11 +30,13 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.LauncherAppState;
import com.android.launcher3.R;
import com.android.launcher3.Reorderable;
import com.android.launcher3.dragndrop.DraggableView;
+import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.data.AppPairInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.MultiTranslateDelegate;
import com.android.launcher3.views.ActivityContext;
@@ -108,22 +110,42 @@
// For some reason, app icons have setIncludeFontPadding(false) inside folders, so we set it
// here to match that.
icon.mAppPairName.setIncludeFontPadding(container != DISPLAY_FOLDER);
- icon.mAppPairName.applyLabel(appPairInfo);
+ // Set title text and accessibility title text.
+ icon.updateTitleAndA11yTitle();
- // Set up accessibility
- icon.setContentDescription(icon.getAccessibilityTitle(appPairInfo));
icon.setAccessibilityDelegate(activity.getAccessibilityDelegate());
return icon;
}
/**
- * Returns a formatted accessibility title for app pairs.
+ * Updates the title and a11y title of the app pair. Called on creation and when packages
+ * change, to reflect app name changes or user language changes.
*/
- public String getAccessibilityTitle(AppPairInfo appPairInfo) {
- CharSequence app1 = appPairInfo.getFirstApp().title;
- CharSequence app2 = appPairInfo.getSecondApp().title;
- return getContext().getString(R.string.app_pair_name_format, app1, app2);
+ public void updateTitleAndA11yTitle() {
+ updateTitleAndTextView();
+ updateAccessibilityTitle();
+ }
+
+ /**
+ * Updates AppPairInfo with a formatted app pair title, and sets it on the BubbleTextView.
+ */
+ public void updateTitleAndTextView() {
+ CharSequence newTitle = getInfo().generateTitle(getContext());
+ mAppPairName.setText(newTitle);
+ }
+
+ /**
+ * Updates the accessibility title with a formatted string template.
+ */
+ public void updateAccessibilityTitle() {
+ CharSequence app1 = getInfo().getFirstApp().title;
+ CharSequence app2 = getInfo().getSecondApp().title;
+ String a11yTitle = getContext().getString(R.string.app_pair_name_format, app1, app2);
+ setContentDescription(
+ getInfo().shouldDrawAsDisabled(getContext())
+ ? getContext().getString(R.string.disabled_app_label, a11yTitle)
+ : a11yTitle);
}
// Required for DraggableView
@@ -179,13 +201,26 @@
return mIconGraphic;
}
+ public int getContainer() {
+ return mContainer;
+ }
+
+ /**
+ * Ensures that both app icons in the pair are loaded in high resolution.
+ */
+ public void verifyHighRes() {
+ IconCache iconCache = LauncherAppState.getInstance(getContext()).getIconCache();
+ getInfo().fetchHiResIconsIfNeeded(iconCache);
+ }
+
/**
* Called when WorkspaceItemInfos get updated, and the app pair icon may need to be redrawn.
*/
- public void maybeRedrawForWorkspaceUpdate(Predicate<WorkspaceItemInfo> itemCheck) {
+ public void maybeRedrawForWorkspaceUpdate(Predicate<ItemInfo> itemCheck) {
// If either of the app pair icons return true on the predicate (i.e. in the list of
// updated apps), redraw the icon graphic (icon background and both icons).
if (getInfo().anyMatch(itemCheck)) {
+ updateTitleAndA11yTitle();
mIconGraphic.redraw();
}
}
diff --git a/src/com/android/launcher3/apppairs/AppPairIconDrawable.java b/src/com/android/launcher3/apppairs/AppPairIconDrawable.java
index c0ac11a..db83d91 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconDrawable.java
+++ b/src/com/android/launcher3/apppairs/AppPairIconDrawable.java
@@ -32,7 +32,7 @@
* A composed Drawable consisting of the two app pair icons and the background behind them (looks
* like two rectangles).
*/
-class AppPairIconDrawable extends Drawable {
+public class AppPairIconDrawable extends Drawable {
private final Paint mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final AppPairIconDrawingParams mP;
private final FastBitmapDrawable mIcon1;
@@ -102,6 +102,7 @@
}
mIcon2.draw(canvas);
+ canvas.restore();
}
/**
@@ -205,4 +206,14 @@
public void setColorFilter(ColorFilter colorFilter) {
mBackgroundPaint.setColorFilter(colorFilter);
}
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mP.getIconSize();
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mP.getIconSize();
+ }
}
diff --git a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
index 62e5771..45dc013 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
+++ b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
@@ -20,6 +20,7 @@
import com.android.launcher3.BubbleTextView.DISPLAY_FOLDER
import com.android.launcher3.DeviceProfile
import com.android.launcher3.R
+import com.android.launcher3.util.Themes
import com.android.launcher3.views.ActivityContext
class AppPairIconDrawingParams(val context: Context, container: Int) {
@@ -62,7 +63,7 @@
// The app pair icon appears differently in portrait and landscape.
var isLeftRightSplit: Boolean = true
// The background paint color (based on container).
- val bgColor: Int
+ var bgColor: Int = 0
init {
val activity: ActivityContext = ActivityContext.lookupContext(context)
@@ -77,22 +78,21 @@
innerPadding = iconSize * INNER_PADDING_SCALE
memberIconSize = iconSize * MEMBER_ICON_SCALE
updateOrientation(dp)
- if (container == DISPLAY_FOLDER) {
- val ta =
- context.theme.obtainStyledAttributes(
- intArrayOf(R.attr.materialColorSurfaceContainerLowest)
- )
- bgColor = ta.getColor(0, 0)
- ta.recycle()
- } else {
- val ta = context.theme.obtainStyledAttributes(R.styleable.FolderIconPreview)
- bgColor = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0)
- ta.recycle()
- }
+ updateBgColor(container)
}
/** Checks the device orientation and updates isLeftRightSplit accordingly. */
fun updateOrientation(dp: DeviceProfile) {
isLeftRightSplit = dp.isLeftRightSplit
}
+
+ fun updateBgColor(container: Int) {
+ if (container == DISPLAY_FOLDER) {
+ bgColor = Themes.getAttrColor(context, R.attr.appPairSurfaceInFolder)
+ } else {
+ val ta = context.theme.obtainStyledAttributes(R.styleable.FolderIconPreview)
+ bgColor = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0)
+ ta.recycle()
+ }
+ }
}
diff --git a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
index a3a1cfc..7809102 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
+++ b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
@@ -19,7 +19,6 @@
import android.content.Context
import android.graphics.Canvas
import android.graphics.Rect
-import android.graphics.drawable.Drawable
import android.util.AttributeSet
import android.view.Gravity
import android.widget.FrameLayout
@@ -27,7 +26,6 @@
import com.android.launcher3.DeviceProfile
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener
import com.android.launcher3.icons.BitmapInfo
-import com.android.launcher3.icons.FastBitmapDrawable.getDisabledColorFilter
import com.android.launcher3.model.data.AppPairInfo
import com.android.launcher3.util.Themes
import com.android.launcher3.views.ActivityContext
@@ -44,15 +42,12 @@
private val TAG = "AppPairIconGraphic"
companion object {
- /**
- * Composes a drawable for this icon, consisting of a background and 2 app icons. The app
- * pair will draw as "disabled" if either of the following is true:
- * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is
- * paused or can't be launched for some other reason).
- * 2) One of the member apps can't be launched due to screen size requirements.
- */
+ /** Composes a drawable for this icon, consisting of a background and 2 app icons. */
@JvmStatic
- fun composeDrawable(appPairInfo: AppPairInfo, p: AppPairIconDrawingParams): Drawable {
+ fun composeDrawable(
+ appPairInfo: AppPairInfo,
+ p: AppPairIconDrawingParams
+ ): AppPairIconDrawable {
// Generate new icons, using themed flag if needed.
val flags = if (Themes.isThemedIconEnabled(p.context)) BitmapInfo.FLAG_THEMED else 0
val appIcon1 = appPairInfo.getFirstApp().newIcon(p.context, flags)
@@ -60,28 +55,17 @@
appIcon1.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt())
appIcon2.setBounds(0, 0, p.memberIconSize.toInt(), p.memberIconSize.toInt())
- val shouldDrawAsDisabled =
- appPairInfo.isDisabled || !appPairInfo.isLaunchable(p.context)
-
- // Set disabled status on icons.
- appIcon1.setIsDisabled(shouldDrawAsDisabled)
- appIcon2.setIsDisabled(shouldDrawAsDisabled)
-
// Create icon drawable.
val fullIconDrawable = AppPairIconDrawable(p, appIcon1, appIcon2)
fullIconDrawable.setBounds(0, 0, p.iconSize, p.iconSize)
- // Set disabled color filter on background paint.
- fullIconDrawable.colorFilter =
- if (shouldDrawAsDisabled) getDisabledColorFilter() else null
-
return fullIconDrawable
}
}
private lateinit var parentIcon: AppPairIcon
private lateinit var drawParams: AppPairIconDrawingParams
- private lateinit var drawable: Drawable
+ lateinit var drawable: AppPairIconDrawable
fun init(icon: AppPairIcon, container: Int) {
parentIcon = icon
@@ -116,10 +100,13 @@
redraw()
}
- /** Updates the icon drawable and redraws it */
- fun redraw() {
- drawable = composeDrawable(parentIcon.info, drawParams)
- invalidate()
+ /**
+ * When the icon is temporary moved to a different colored surface, update the background color.
+ * Calling this method with [null] reverts the icon back to its default color.
+ */
+ fun onTemporaryContainerChange(newContainer: Int?) {
+ drawParams.updateBgColor(newContainer ?: parentIcon.container)
+ redraw()
}
/**
@@ -136,6 +123,12 @@
)
}
+ /** Updates the icon drawable and redraws it */
+ fun redraw() {
+ drawable = composeDrawable(parentIcon.info, drawParams)
+ invalidate()
+ }
+
override fun dispatchDraw(canvas: Canvas) {
super.dispatchDraw(canvas)
drawable.draw(canvas)
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 474108e..5c74108 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -19,6 +19,9 @@
import static android.text.TextUtils.isEmpty;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.LauncherState.EDIT_MODE;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
@@ -66,14 +69,12 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Alarm;
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.Launcher;
-import com.android.launcher3.LauncherSettings;
import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
@@ -166,6 +167,22 @@
private static final Rect sTempRect = new Rect();
private static final int MIN_FOLDERS_FOR_HARDWARE_OPTIMIZATION = 10;
+ /**
+ * Checks if {@code o} is an {@link ItemInfo} type that can be placed in folders.
+ */
+ public static boolean willAccept(Object o) {
+ return o instanceof ItemInfo info && willAcceptItemType(info.itemType);
+ }
+
+ /**
+ * Checks if {@code itemType} is a type that can be placed in folders.
+ */
+ public static boolean willAcceptItemType(int itemType) {
+ return itemType == ITEM_TYPE_APPLICATION
+ || itemType == ITEM_TYPE_DEEP_SHORTCUT
+ || itemType == ITEM_TYPE_APP_PAIR;
+ }
+
private final Alarm mReorderAlarm = new Alarm(Looper.getMainLooper());
private final Alarm mOnExitAlarm = new Alarm(Looper.getMainLooper());
private final Alarm mOnScrollHintAlarm = new Alarm(Looper.getMainLooper());
@@ -310,9 +327,7 @@
public boolean startDrag(View v, DragOptions options) {
Object tag = v.getTag();
- if (tag instanceof WorkspaceItemInfo) {
- WorkspaceItemInfo item = (WorkspaceItemInfo) tag;
-
+ if (tag instanceof ItemInfo item) {
mEmptyCellRank = item.rank;
mCurrentDragView = v;
@@ -343,14 +358,12 @@
}
mContent.removeItem(mCurrentDragView);
- if (dragObject.dragInfo instanceof WorkspaceItemInfo) {
- mItemsInvalidated = true;
+ mItemsInvalidated = true;
- // We do not want to get events for the item being removed, as they will get handled
- // when the drop completes
- try (SuppressInfoChanges s = new SuppressInfoChanges()) {
- mInfo.remove((WorkspaceItemInfo) dragObject.dragInfo, true);
- }
+ // We do not want to get events for the item being removed, as they will get handled
+ // when the drop completes
+ try (SuppressInfoChanges s = new SuppressInfoChanges()) {
+ mInfo.remove(dragObject.dragInfo, true);
}
mDragInProgress = true;
mItemAddedBackToSelfViaIcon = false;
@@ -490,7 +503,7 @@
mInfo = info;
mFromTitle = info.title;
mFromLabelState = info.getFromLabelState();
- ArrayList<WorkspaceItemInfo> children = info.getContents();
+ ArrayList<ItemInfo> children = info.getContents();
Collections.sort(children, ITEM_POS_COMPARATOR);
updateItemLocationsInDatabaseBatch(true);
@@ -623,7 +636,7 @@
// onDropComplete. Perform cleanup once drag-n-drop ends.
mDragController.addDragListener(this);
- ArrayList<WorkspaceItemInfo> items = new ArrayList<>(mInfo.getContents());
+ ArrayList<ItemInfo> items = new ArrayList<>(mInfo.getContents());
mEmptyCellRank = items.size();
items.add(null); // Add an empty spot at the end
@@ -644,7 +657,7 @@
* is animated relative to the specified View. If the View is null, no animation
* is played.
*/
- private void animateOpen(List<WorkspaceItemInfo> items, int pageNo) {
+ private void animateOpen(List<ItemInfo> items, int pageNo) {
if (items == null || items.size() <= 1) {
Log.d(TAG, "Couldn't animate folder open because items is: " + items);
return;
@@ -893,8 +906,7 @@
public boolean acceptDrop(DragObject d) {
final ItemInfo item = d.dragInfo;
final int itemType = item.itemType;
- return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT));
+ return Folder.willAcceptItemType(itemType);
}
public void onDragEnter(DragObject d) {
@@ -1047,7 +1059,7 @@
}
} else {
// The drag failed, we need to return the item to the folder
- WorkspaceItemInfo info = (WorkspaceItemInfo) d.dragInfo;
+ ItemInfo info = d.dragInfo;
View icon = (mCurrentDragView != null && mCurrentDragView.getTag() == info)
? mCurrentDragView : mContent.createNewView(info);
ArrayList<View> views = getIconsInReadingOrder();
@@ -1096,7 +1108,7 @@
ArrayList<ItemInfo> items = new ArrayList<>();
int total = mInfo.getContents().size();
for (int i = 0; i < total; i++) {
- WorkspaceItemInfo itemInfo = mInfo.getContents().get(i);
+ ItemInfo itemInfo = mInfo.getContents().get(i);
if (verifier.updateRankAndPos(itemInfo, i)) {
items.add(itemInfo);
}
@@ -1109,8 +1121,7 @@
Executors.MODEL_EXECUTOR.post(() -> {
FolderNameInfos nameInfos = new FolderNameInfos();
FolderNameProvider fnp = FolderNameProvider.newInstance(getContext());
- fnp.getSuggestedFolderName(
- getContext(), mInfo.getContents(), nameInfos);
+ fnp.getSuggestedFolderName(getContext(), mInfo.getAppContents(), nameInfos);
mInfo.suggestedFolderNames = nameInfos;
});
}
@@ -1295,15 +1306,15 @@
d.deferDragViewCleanupPostAnimation = false;
mRearrangeOnClose = true;
} else {
- final WorkspaceItemInfo si;
+ final ItemInfo si;
if (pasiSi != null) {
si = pasiSi;
} else if (d.dragInfo instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy.
si = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(launcher);
} else {
- // WorkspaceItemInfo
- si = (WorkspaceItemInfo) d.dragInfo;
+ // WorkspaceItemInfo or AppPairInfo
+ si = d.dragInfo;
}
View currentDragView;
@@ -1311,7 +1322,7 @@
currentDragView = mContent.createAndAddViewForRank(si, mEmptyCellRank);
// Actually move the item in the database if it was an external drag. Call this
- // before creating the view, so that WorkspaceItemInfo is updated appropriately.
+ // before creating the view, so that the ItemInfo is updated appropriately.
mLauncherDelegate.getModelWriter().addOrMoveItemInDatabase(
si, mInfo.id, 0, si.cellX, si.cellY);
mIsExternalDrag = false;
@@ -1373,14 +1384,14 @@
// This is used so the item doesn't immediately appear in the folder when added. In one case
// we need to create the illusion that the item isn't added back to the folder yet, to
// to correspond to the animation of the icon back into the folder. This is
- public void hideItem(WorkspaceItemInfo info) {
+ public void hideItem(ItemInfo info) {
View v = getViewForInfo(info);
if (v != null) {
v.setVisibility(INVISIBLE);
}
}
- public void showItem(WorkspaceItemInfo info) {
+ public void showItem(ItemInfo info) {
View v = getViewForInfo(info);
if (v != null) {
v.setVisibility(VISIBLE);
@@ -1388,7 +1399,7 @@
}
@Override
- public void onAdd(WorkspaceItemInfo item, int rank) {
+ public void onAdd(ItemInfo item, int rank) {
FolderGridOrganizer verifier = new FolderGridOrganizer(
mActivityContext.getDeviceProfile()).setFolderInfo(mInfo);
verifier.updateRankAndPos(item, rank);
@@ -1403,7 +1414,7 @@
}
@Override
- public void onRemove(List<WorkspaceItemInfo> items) {
+ public void onRemove(List<ItemInfo> items) {
mItemsInvalidated = true;
items.stream().map(this::getViewForInfo).forEach(mContent::removeItem);
if (mState == STATE_ANIMATING) {
@@ -1420,7 +1431,7 @@
}
}
- private View getViewForInfo(final WorkspaceItemInfo item) {
+ private View getViewForInfo(final ItemInfo item) {
return mContent.iterateOverItems((info, view) -> info == item);
}
@@ -1448,7 +1459,7 @@
return mItemsInReadingOrder;
}
- public List<BubbleTextView> getItemsOnPage(int page) {
+ public List<View> getItemsOnPage(int page) {
ArrayList<View> allItems = getIconsInReadingOrder();
int lastPage = mContent.getPageCount() - 1;
int totalItemsInFolder = allItems.size();
@@ -1460,9 +1471,9 @@
int startIndex = page * itemsPerPage;
int endIndex = Math.min(startIndex + numItemsOnCurrentPage, allItems.size());
- List<BubbleTextView> itemsOnCurrentPage = new ArrayList<>(numItemsOnCurrentPage);
+ List<View> itemsOnCurrentPage = new ArrayList<>(numItemsOnCurrentPage);
for (int i = startIndex; i < endIndex; ++i) {
- itemsOnCurrentPage.add((BubbleTextView) allItems.get(i));
+ itemsOnCurrentPage.add(allItems.get(i));
}
return itemsOnCurrentPage;
}
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index a91373b..7a2ec97 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -43,6 +43,7 @@
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PropertyResetListener;
+import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BaseDragLayer;
@@ -127,7 +128,7 @@
(BaseDragLayer.LayoutParams) mFolder.getLayoutParams();
mFolderIcon.getPreviewItemManager().recomputePreviewDrawingParams();
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
- final List<BubbleTextView> itemsInPreview = getPreviewIconsOnPage(0);
+ final List<View> itemsInPreview = getPreviewIconsOnPage(0);
// Match position of the FolderIcon
final Rect folderIconPos = new Rect();
@@ -139,8 +140,8 @@
// Match size/scale of icons in the preview
float previewScale = rule.scaleForItem(itemsInPreview.size());
float previewSize = rule.getIconSize() * previewScale;
- float initialScale = previewSize / itemsInPreview.get(0).getIconSize()
- * scaleRelativeToDragLayer;
+ float baseIconSize = getBubbleTextView(itemsInPreview.get(0)).getIconSize();
+ float initialScale = previewSize / baseIconSize * scaleRelativeToDragLayer;
final float finalScale = 1f;
float scale = mIsOpening ? initialScale : finalScale;
mFolder.setPivotX(0);
@@ -198,11 +199,12 @@
// Initialize the Folder items' text.
PropertyResetListener colorResetListener =
new PropertyResetListener<>(TEXT_ALPHA_PROPERTY, 1f);
- for (BubbleTextView icon : mFolder.getItemsOnPage(mFolder.mContent.getCurrentPage())) {
+ for (View icon : mFolder.getItemsOnPage(mFolder.mContent.getCurrentPage())) {
+ BubbleTextView titleText = getBubbleTextView(icon);
if (mIsOpening) {
- icon.setTextVisibility(false);
+ titleText.setTextVisibility(false);
}
- ObjectAnimator anim = icon.createTextAlphaAnimator(mIsOpening);
+ ObjectAnimator anim = titleText.createTextAlphaAnimator(mIsOpening);
anim.addListener(colorResetListener);
play(a, anim);
}
@@ -339,7 +341,7 @@
/**
* Returns the list of "preview items" on {@param page}.
*/
- private List<BubbleTextView> getPreviewIconsOnPage(int page) {
+ private List<View> getPreviewIconsOnPage(int page) {
return mPreviewVerifier.setFolderInfo(mFolder.mInfo)
.previewItemsForPage(page, mFolder.getIconsInReadingOrder());
}
@@ -351,7 +353,7 @@
int previewItemOffsetX, int previewItemOffsetY) {
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
boolean isOnFirstPage = mFolder.mContent.getCurrentPage() == 0;
- final List<BubbleTextView> itemsInPreview = getPreviewIconsOnPage(
+ final List<View> itemsInPreview = getPreviewIconsOnPage(
isOnFirstPage ? 0 : mFolder.mContent.getCurrentPage());
final int numItemsInPreview = itemsInPreview.size();
final int numItemsInFirstPagePreview = isOnFirstPage
@@ -361,48 +363,49 @@
ShortcutAndWidgetContainer cwc = mContent.getPageAt(0).getShortcutsAndWidgets();
for (int i = 0; i < numItemsInPreview; ++i) {
- final BubbleTextView btv = itemsInPreview.get(i);
- CellLayoutLayoutParams btvLp = (CellLayoutLayoutParams) btv.getLayoutParams();
+ final View v = itemsInPreview.get(i);
+ CellLayoutLayoutParams vLp = (CellLayoutLayoutParams) v.getLayoutParams();
// Calculate the final values in the LayoutParams.
- btvLp.isLockedToGrid = true;
- cwc.setupLp(btv);
+ vLp.isLockedToGrid = true;
+ cwc.setupLp(v);
// Match scale of icons in the preview of the items on the first page.
float previewScale = rule.scaleForItem(numItemsInFirstPagePreview);
float previewSize = rule.getIconSize() * previewScale;
- float iconScale = previewSize / itemsInPreview.get(i).getIconSize();
+ float baseIconSize = getBubbleTextView(v).getIconSize();
+ float iconScale = previewSize / baseIconSize;
final float initialScale = iconScale / folderScale;
final float finalScale = 1f;
float scale = mIsOpening ? initialScale : finalScale;
- btv.setScaleX(scale);
- btv.setScaleY(scale);
+ v.setScaleX(scale);
+ v.setScaleY(scale);
// Match positions of the icons in the folder with their positions in the preview
rule.computePreviewItemDrawingParams(i, numItemsInFirstPagePreview, mTmpParams);
// The PreviewLayoutRule assumes that the icon size takes up the entire width so we
// offset by the actual size.
- int iconOffsetX = (int) ((btvLp.width - btv.getIconSize()) * iconScale) / 2;
+ int iconOffsetX = (int) ((vLp.width - baseIconSize) * iconScale) / 2;
final int previewPosX =
(int) ((mTmpParams.transX - iconOffsetX + previewItemOffsetX) / folderScale);
- final float paddingTop = btv.getPaddingTop() * iconScale;
+ final float paddingTop = v.getPaddingTop() * iconScale;
final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY - paddingTop)
/ folderScale);
- final float xDistance = previewPosX - btvLp.x;
- final float yDistance = previewPosY - btvLp.y;
+ final float xDistance = previewPosX - vLp.x;
+ final float yDistance = previewPosY - vLp.y;
- Animator translationX = getAnimator(btv, View.TRANSLATION_X, xDistance, 0f);
+ Animator translationX = getAnimator(v, View.TRANSLATION_X, xDistance, 0f);
translationX.setInterpolator(previewItemInterpolator);
play(animatorSet, translationX);
- Animator translationY = getAnimator(btv, View.TRANSLATION_Y, yDistance, 0f);
+ Animator translationY = getAnimator(v, View.TRANSLATION_Y, yDistance, 0f);
translationY.setInterpolator(previewItemInterpolator);
play(animatorSet, translationY);
- Animator scaleAnimator = getAnimator(btv, SCALE_PROPERTY, initialScale, finalScale);
+ Animator scaleAnimator = getAnimator(v, SCALE_PROPERTY, initialScale, finalScale);
scaleAnimator.setInterpolator(previewItemInterpolator);
play(animatorSet, scaleAnimator);
@@ -426,20 +429,20 @@
super.onAnimationStart(animation);
// Necessary to initialize values here because of the start delay.
if (mIsOpening) {
- btv.setTranslationX(xDistance);
- btv.setTranslationY(yDistance);
- btv.setScaleX(initialScale);
- btv.setScaleY(initialScale);
+ v.setTranslationX(xDistance);
+ v.setTranslationY(yDistance);
+ v.setScaleX(initialScale);
+ v.setScaleY(initialScale);
}
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- btv.setTranslationX(0.0f);
- btv.setTranslationY(0.0f);
- btv.setScaleX(1f);
- btv.setScaleY(1f);
+ v.setTranslationX(0.0f);
+ v.setTranslationY(0.0f);
+ v.setScaleX(1f);
+ v.setScaleY(1f);
}
});
}
@@ -482,4 +485,15 @@
? ObjectAnimator.ofArgb(drawable, property, v1, v2)
: ObjectAnimator.ofArgb(drawable, property, v2, v1);
}
+
+ /**
+ * Gets the {@link com.android.launcher3.BubbleTextView} from an icon. In some cases the
+ * BubbleTextView is the whole icon itself, while in others it is contained within the view and
+ * only serves to store the title text.
+ */
+ private BubbleTextView getBubbleTextView(View v) {
+ return v instanceof AppPairIcon
+ ? ((AppPairIcon) v).getTitleTextView()
+ : (BubbleTextView) v;
+ }
}
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 62ce311..6b30b95 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -71,6 +71,7 @@
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
+import com.android.launcher3.model.data.AppPairInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.FolderInfo.LabelState;
@@ -118,7 +119,7 @@
ClippedFolderIconLayoutRule mPreviewLayoutRule;
private PreviewItemManager mPreviewItemManager;
private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0);
- private List<WorkspaceItemInfo> mCurrentPreviewItems = new ArrayList<>();
+ private List<ItemInfo> mCurrentPreviewItems = new ArrayList<>();
boolean mAnimating = false;
@@ -215,7 +216,7 @@
// Keep the notification dot up to date with the sum of all the content's dots.
FolderDotInfo folderDotInfo = new FolderDotInfo();
- for (WorkspaceItemInfo si : folderInfo.getContents()) {
+ for (ItemInfo si : folderInfo.getContents()) {
folderDotInfo.addDotInfo(activity.getDotInfoForItem(si));
}
icon.setDotInfo(folderDotInfo);
@@ -261,20 +262,18 @@
private boolean willAcceptItem(ItemInfo item) {
final int itemType = item.itemType;
- return ((itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
- itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) &&
- item != mInfo && !mFolder.isOpen());
+ return (Folder.willAcceptItemType(itemType) && item != mInfo && !mFolder.isOpen());
}
public boolean acceptDrop(ItemInfo dragInfo) {
return !mFolder.isDestroyed() && willAcceptItem(dragInfo);
}
- public void addItem(WorkspaceItemInfo item) {
+ public void addItem(ItemInfo item) {
mInfo.add(item, true);
}
- public void removeItem(WorkspaceItemInfo item, boolean animate) {
+ public void removeItem(ItemInfo item, boolean animate) {
mInfo.remove(item, animate);
}
@@ -287,8 +286,8 @@
mOpenAlarm.setOnAlarmListener(mOnOpenListener);
if (SPRING_LOADING_ENABLED &&
((dragInfo instanceof WorkspaceItemFactory)
- || (dragInfo instanceof WorkspaceItemInfo)
- || (dragInfo instanceof PendingAddShortcutInfo))) {
+ || (dragInfo instanceof PendingAddShortcutInfo)
+ || Folder.willAccept(dragInfo))) {
mOpenAlarm.setAlarm(ON_OPEN_DELAY);
}
}
@@ -303,8 +302,8 @@
return mPreviewItemManager.prepareCreateAnimation(destView);
}
- public void performCreateAnimation(final WorkspaceItemInfo destInfo, final View destView,
- final WorkspaceItemInfo srcInfo, final DragObject d, Rect dstRect,
+ public void performCreateAnimation(final ItemInfo destInfo, final View destView,
+ final ItemInfo srcInfo, final DragObject d, Rect dstRect,
float scaleRelativeToDragLayer) {
final DragView srcView = d.dragView;
prepareCreateAnimation(destView);
@@ -330,7 +329,7 @@
mOpenAlarm.cancelAlarm();
}
- private void onDrop(final WorkspaceItemInfo item, DragObject d, Rect finalRect,
+ private void onDrop(final ItemInfo item, DragObject d, Rect finalRect,
float scaleRelativeToDragLayer, int index, boolean itemReturnedOnFailedDrop) {
item.cellX = -1;
item.cellY = -1;
@@ -361,7 +360,7 @@
int numItemsInPreview = Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index + 1);
boolean itemAdded = false;
if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) {
- List<WorkspaceItemInfo> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
+ List<ItemInfo> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems);
mInfo.add(item, index, false);
mCurrentPreviewItems.clear();
mCurrentPreviewItems.addAll(getPreviewItemsOnPage(0));
@@ -422,7 +421,7 @@
FolderNameInfos nameInfos = new FolderNameInfos();
Executors.MODEL_EXECUTOR.post(() -> {
d.folderNameProvider.getSuggestedFolderName(
- getContext(), mInfo.getContents(), nameInfos);
+ getContext(), mInfo.getAppContents(), nameInfos);
postDelayed(() -> {
setLabelSuggestion(nameInfos, d.logInstanceId);
invalidate();
@@ -475,15 +474,21 @@
public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
- WorkspaceItemInfo item;
+ ItemInfo item;
if (d.dragInfo instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy
item = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(getContext());
} else if (d.dragSource instanceof BaseItemDragListener){
// Came from a different window -- make a copy
- item = new WorkspaceItemInfo((WorkspaceItemInfo) d.dragInfo);
+ if (d.dragInfo instanceof AppPairInfo) {
+ // dragged item is app pair
+ item = new AppPairInfo((AppPairInfo) d.dragInfo);
+ } else {
+ // dragged item is WorkspaceItemInfo
+ item = new WorkspaceItemInfo((WorkspaceItemInfo) d.dragInfo);
+ }
} else {
- item = (WorkspaceItemInfo) d.dragInfo;
+ item = d.dragInfo;
}
mFolder.notifyDrop();
onDrop(item, d, null, 1.0f,
@@ -665,7 +670,7 @@
/**
* Returns the list of items which should be visible in the preview
*/
- public List<WorkspaceItemInfo> getPreviewItemsOnPage(int page) {
+ public List<ItemInfo> getPreviewItemsOnPage(int page) {
return mPreviewVerifier.setFolderInfo(mInfo).previewItemsForPage(page, mInfo.getContents());
}
@@ -690,12 +695,12 @@
/**
* Updates the preview items which match the provided condition
*/
- public void updatePreviewItems(Predicate<WorkspaceItemInfo> itemCheck) {
+ public void updatePreviewItems(Predicate<ItemInfo> itemCheck) {
mPreviewItemManager.updatePreviewItems(itemCheck);
}
@Override
- public void onAdd(WorkspaceItemInfo item, int rank) {
+ public void onAdd(ItemInfo item, int rank) {
updatePreviewItems(false);
boolean wasDotted = mDotInfo.hasDot();
mDotInfo.addDotInfo(mActivity.getDotInfoForItem(item));
@@ -707,7 +712,7 @@
}
@Override
- public void onRemove(List<WorkspaceItemInfo> items) {
+ public void onRemove(List<ItemInfo> items) {
updatePreviewItems(false);
boolean wasDotted = mDotInfo.hasDot();
items.stream().map(mActivity::getDotInfoForItem).forEach(mDotInfo::subtractDotInfo);
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index f2bed92..8eaa0dc 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -41,8 +41,10 @@
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
import com.android.launcher3.Utilities;
+import com.android.launcher3.apppairs.AppPairIcon;
import com.android.launcher3.celllayout.CellLayoutLayoutParams;
import com.android.launcher3.keyboard.ViewGroupFocusHelper;
+import com.android.launcher3.model.data.AppPairInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
@@ -148,7 +150,7 @@
/**
* Binds items to the layout.
*/
- public void bindItems(List<WorkspaceItemInfo> items) {
+ public void bindItems(List<ItemInfo> items) {
if (mViewsBound) {
unbindItems();
}
@@ -164,8 +166,11 @@
CellLayout page = (CellLayout) getChildAt(i);
ShortcutAndWidgetContainer container = page.getShortcutsAndWidgets();
for (int j = container.getChildCount() - 1; j >= 0; j--) {
- container.getChildAt(j).setVisibility(View.VISIBLE);
- mViewCache.recycleView(R.layout.folder_application, container.getChildAt(j));
+ View iconView = container.getChildAt(j);
+ iconView.setVisibility(View.VISIBLE);
+ if (iconView instanceof BubbleTextView) {
+ mViewCache.recycleView(R.layout.folder_application, iconView);
+ }
}
page.removeAllViews();
mViewCache.recycleView(R.layout.folder_page, page);
@@ -185,7 +190,7 @@
* Creates and adds an icon corresponding to the provided rank
* @return the created icon
*/
- public View createAndAddViewForRank(WorkspaceItemInfo item, int rank) {
+ public View createAndAddViewForRank(ItemInfo item, int rank) {
View icon = createNewView(item);
if (!mViewsBound) {
return icon;
@@ -200,7 +205,7 @@
* Adds the {@param view} to the layout based on {@param rank} and updated the position
* related attributes. It assumes that {@param item} is already attached to the view.
*/
- public void addViewForRank(View view, WorkspaceItemInfo item, int rank) {
+ public void addViewForRank(View view, ItemInfo item, int rank) {
int pageNo = rank / mOrganizer.getMaxItemsPerPage();
CellLayoutLayoutParams lp = (CellLayoutLayoutParams) view.getLayoutParams();
@@ -209,26 +214,36 @@
}
@SuppressLint("InflateParams")
- public View createNewView(WorkspaceItemInfo item) {
+ public View createNewView(ItemInfo item) {
if (item == null) {
return null;
}
- final BubbleTextView textView = mViewCache.getView(
- R.layout.folder_application, getContext(), null);
- textView.applyFromWorkspaceItem(item);
- textView.setOnClickListener(mFolder.mActivityContext.getItemOnClickListener());
- textView.setOnLongClickListener(mFolder);
- textView.setOnFocusChangeListener(mFocusIndicatorHelper);
- CellLayoutLayoutParams lp = (CellLayoutLayoutParams) textView.getLayoutParams();
+
+ final View icon;
+ if (item instanceof AppPairInfo api) {
+ // TODO (b/332607759): Make view cache work with app pair icons
+ icon = AppPairIcon.inflateIcon(R.layout.folder_app_pair, ActivityContext.lookupContext(
+ getContext()), null , api, BubbleTextView.DISPLAY_FOLDER);
+ } else {
+ icon = mViewCache.getView(R.layout.folder_application, getContext(), null);
+ ((BubbleTextView) icon).applyFromWorkspaceItem((WorkspaceItemInfo) item);
+ }
+
+ icon.setOnClickListener(mFolder.mActivityContext.getItemOnClickListener());
+ icon.setOnLongClickListener(mFolder);
+ icon.setOnFocusChangeListener(mFocusIndicatorHelper);
+
+ CellLayoutLayoutParams lp = (CellLayoutLayoutParams) icon.getLayoutParams();
if (lp == null) {
- textView.setLayoutParams(new CellLayoutLayoutParams(
+ icon.setLayoutParams(new CellLayoutLayoutParams(
item.cellX, item.cellY, item.spanX, item.spanY));
} else {
lp.setCellX(item.cellX);
lp.setCellY(item.cellY);
lp.cellHSpan = lp.cellVSpan = 1;
}
- return textView;
+
+ return icon;
}
@Nullable
@@ -497,13 +512,20 @@
if (page != null) {
ShortcutAndWidgetContainer parent = page.getShortcutsAndWidgets();
for (int i = parent.getChildCount() - 1; i >= 0; i--) {
- BubbleTextView icon = ((BubbleTextView) parent.getChildAt(i));
- icon.verifyHighRes();
+ View iconView = parent.getChildAt(i);
+ Drawable d = null;
+ if (iconView instanceof BubbleTextView btv) {
+ btv.verifyHighRes();
+ d = btv.getIcon();
+ } else if (iconView instanceof AppPairIcon api) {
+ api.verifyHighRes();
+ d = api.getIconDrawableArea().getDrawable();
+ }
+
// Set the callback back to the actual icon, in case
// it was captured by the FolderIcon
- Drawable d = icon.getIcon();
if (d != null) {
- d.setCallback(icon);
+ d.setCallback(iconView);
}
}
}
diff --git a/src/com/android/launcher3/folder/LauncherDelegate.java b/src/com/android/launcher3/folder/LauncherDelegate.java
index 33bcf21..07215c4 100644
--- a/src/com/android/launcher3/folder/LauncherDelegate.java
+++ b/src/com/android/launcher3/folder/LauncherDelegate.java
@@ -33,7 +33,7 @@
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.model.data.FolderInfo;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
@@ -86,7 +86,7 @@
FolderInfo info = folder.mInfo;
if (itemCount <= 1) {
View newIcon = null;
- WorkspaceItemInfo finalItem = null;
+ ItemInfo finalItem = null;
if (itemCount == 1) {
// Move the item from the folder to the workspace, in the position of the
diff --git a/src/com/android/launcher3/folder/PreviewItemDrawingParams.java b/src/com/android/launcher3/folder/PreviewItemDrawingParams.java
index 58efdc1..0faa1c9 100644
--- a/src/com/android/launcher3/folder/PreviewItemDrawingParams.java
+++ b/src/com/android/launcher3/folder/PreviewItemDrawingParams.java
@@ -17,7 +17,7 @@
import android.graphics.drawable.Drawable;
-import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.model.data.ItemInfo;
/**
* Manages the parameters used to draw a Folder preview item.
@@ -30,7 +30,7 @@
public FolderPreviewItemAnim anim;
public boolean hidden;
public Drawable drawable;
- public WorkspaceItemInfo item;
+ public ItemInfo item;
PreviewItemDrawingParams(float transX, float transY, float scale) {
this.transX = transX;
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 9001a0c..6311638 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -16,6 +16,7 @@
package com.android.launcher3.folder;
+import static com.android.launcher3.BubbleTextView.DISPLAY_FOLDER;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ENTER_INDEX;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.EXIT_INDEX;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
@@ -41,7 +42,12 @@
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Utilities;
+import com.android.launcher3.apppairs.AppPairIcon;
+import com.android.launcher3.apppairs.AppPairIconDrawingParams;
+import com.android.launcher3.apppairs.AppPairIconGraphic;
import com.android.launcher3.graphics.PreloadIconDrawable;
+import com.android.launcher3.model.data.AppPairInfo;
+import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.util.Themes;
@@ -125,7 +131,9 @@
}
Drawable prepareCreateAnimation(final View destView) {
- Drawable animateDrawable = ((BubbleTextView) destView).getIcon();
+ Drawable animateDrawable = destView instanceof AppPairIcon
+ ? ((AppPairIcon) destView).getIconDrawableArea().getDrawable()
+ : ((BubbleTextView) destView).getIcon();
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(),
destView.getMeasuredWidth());
mReferenceDrawable = animateDrawable;
@@ -258,7 +266,7 @@
}
void buildParamsForPage(int page, ArrayList<PreviewItemDrawingParams> params, boolean animate) {
- List<WorkspaceItemInfo> items = mIcon.getPreviewItemsOnPage(page);
+ List<ItemInfo> items = mIcon.getPreviewItemsOnPage(page);
// We adjust the size of the list to match the number of items in the preview.
while (items.size() < params.size()) {
@@ -328,16 +336,18 @@
mNumOfPrevItems = numOfPrevItemsAux;
}
- void updatePreviewItems(Predicate<WorkspaceItemInfo> itemCheck) {
+ void updatePreviewItems(Predicate<ItemInfo> itemCheck) {
boolean modified = false;
for (PreviewItemDrawingParams param : mFirstPageParams) {
- if (itemCheck.test(param.item)) {
+ if (itemCheck.test(param.item)
+ || (param.item instanceof AppPairInfo api && api.anyMatch(itemCheck))) {
setDrawable(param, param.item);
modified = true;
}
}
for (PreviewItemDrawingParams param : mCurrentPageParams) {
- if (itemCheck.test(param.item)) {
+ if (itemCheck.test(param.item)
+ || (param.item instanceof AppPairInfo api && api.anyMatch(itemCheck))) {
setDrawable(param, param.item);
modified = true;
}
@@ -370,15 +380,14 @@
* @param newItems The list of items in the new preview.
* @param dropped The item that was dropped onto the FolderIcon.
*/
- public void onDrop(List<WorkspaceItemInfo> oldItems, List<WorkspaceItemInfo> newItems,
- WorkspaceItemInfo dropped) {
+ public void onDrop(List<ItemInfo> oldItems, List<ItemInfo> newItems, ItemInfo dropped) {
int numItems = newItems.size();
final ArrayList<PreviewItemDrawingParams> params = mFirstPageParams;
buildParamsForPage(0, params, false);
// New preview items for items that are moving in (except for the dropped item).
- List<WorkspaceItemInfo> moveIn = new ArrayList<>();
- for (WorkspaceItemInfo newItem : newItems) {
+ List<ItemInfo> moveIn = new ArrayList<>();
+ for (ItemInfo newItem : newItems) {
if (!oldItems.contains(newItem) && !newItem.equals(dropped)) {
moveIn.add(newItem);
}
@@ -401,10 +410,10 @@
}
// Old preview items that need to be moved out.
- List<WorkspaceItemInfo> moveOut = new ArrayList<>(oldItems);
+ List<ItemInfo> moveOut = new ArrayList<>(oldItems);
moveOut.removeAll(newItems);
for (int i = 0; i < moveOut.size(); ++i) {
- WorkspaceItemInfo item = moveOut.get(i);
+ ItemInfo item = moveOut.get(i);
int oldIndex = oldItems.indexOf(item);
PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
updateTransitionParam(p, item, oldIndex, EXIT_INDEX, numItems);
@@ -418,7 +427,7 @@
}
}
- private void updateTransitionParam(final PreviewItemDrawingParams p, WorkspaceItemInfo item,
+ private void updateTransitionParam(final PreviewItemDrawingParams p, ItemInfo item,
int prevIndex, int newIndex, int numItems) {
setDrawable(p, item);
@@ -431,16 +440,24 @@
}
@VisibleForTesting
- public void setDrawable(PreviewItemDrawingParams p, WorkspaceItemInfo item) {
- if (item.hasPromiseIconUi() || (item.runtimeStatusFlags
- & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
- PreloadIconDrawable drawable = newPendingIcon(mContext, item);
- p.drawable = drawable;
- } else {
- p.drawable = item.newIcon(mContext,
- Themes.isThemedIconEnabled(mContext) ? FLAG_THEMED : 0);
+ public void setDrawable(PreviewItemDrawingParams p, ItemInfo item) {
+ if (item instanceof WorkspaceItemInfo wii) {
+ if (wii.hasPromiseIconUi() || (wii.runtimeStatusFlags
+ & ItemInfoWithIcon.FLAG_SHOW_DOWNLOAD_PROGRESS_MASK) != 0) {
+ PreloadIconDrawable drawable = newPendingIcon(mContext, wii);
+ p.drawable = drawable;
+ } else {
+ p.drawable = wii.newIcon(mContext,
+ Themes.isThemedIconEnabled(mContext) ? FLAG_THEMED : 0);
+ }
+ p.drawable.setBounds(0, 0, mIconSize, mIconSize);
+ } else if (item instanceof AppPairInfo api) {
+ AppPairIconDrawingParams appPairParams =
+ new AppPairIconDrawingParams(mContext, DISPLAY_FOLDER);
+ p.drawable = AppPairIconGraphic.composeDrawable(api, appPairParams);
+ p.drawable.setBounds(0, 0, mIconSize, mIconSize);
}
- p.drawable.setBounds(0, 0, mIconSize, mIconSize);
+
p.item = item;
// Set the callback to FolderIcon as it is responsible to drawing the icon. The
// callback will be released when the folder is opened.
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index ee9ce7d..886ae27 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -44,6 +44,7 @@
import com.android.launcher3.Workspace;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.AppPairInfo;
import com.android.launcher3.model.data.CollectionInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
@@ -259,10 +260,15 @@
itemsIdMap.put(item.id, item);
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
- case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR:
- collections.put(item.id, (CollectionInfo) item);
+ collections.put(item.id, (FolderInfo) item);
workspaceItems.add(item);
break;
+ case LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR:
+ collections.put(item.id, (AppPairInfo) item);
+ // Fall through here. App pairs are both containers (like folders) and containable
+ // items (can be placed in folders). So we need to add app pairs to the folders
+ // array (above) but also verify the existence of their container, like regular
+ // apps (below).
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
if (item.container == LauncherSettings.Favorites.CONTAINER_DESKTOP ||
@@ -277,7 +283,7 @@
Log.e(TAG, msg);
}
} else {
- findOrMakeFolder(item.container).add((WorkspaceItemInfo) item);
+ findOrMakeFolder(item.container).add(item);
}
}
break;
diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java
index 1deb665..cc20cd1 100644
--- a/src/com/android/launcher3/model/FirstScreenBroadcast.java
+++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java
@@ -115,7 +115,7 @@
for (ItemInfo info : firstScreenItems) {
if (info instanceof CollectionInfo ci) {
String collectionItemInfoPackage;
- for (ItemInfo collectionItemInfo : cloneOnMainThread(ci.getContents())) {
+ for (ItemInfo collectionItemInfo : cloneOnMainThread(ci.getAppContents())) {
collectionItemInfoPackage = getPackageName(collectionItemInfo);
if (collectionItemInfoPackage != null
&& packages.contains(collectionItemInfoPackage)) {
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index f8c76a3..3a23765 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -81,7 +81,6 @@
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.IconRequestInfo;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
@@ -494,9 +493,7 @@
}
appPair.getContents().sort(Folder.ITEM_POS_COMPARATOR);
- // Fetch hi-res icons if needed.
- appPair.getContents().stream().filter(ItemInfoWithIcon::usingLowResIcon)
- .forEach(member -> mIconCache.getTitleAndIcon(member, false));
+ appPair.fetchHiResIconsIfNeeded(mIconCache);
}
}
@@ -566,12 +563,16 @@
// Ranks are the source of truth for folder items, so cellX and cellY can be
// ignored for now. Database will be updated once user manually modifies folder.
for (int rank = 0; rank < size; ++rank) {
- WorkspaceItemInfo info = folder.getContents().get(rank);
+ ItemInfo info = folder.getContents().get(rank);
info.rank = rank;
- if (info.usingLowResIcon() && info.itemType == Favorites.ITEM_TYPE_APPLICATION
+ if (info instanceof WorkspaceItemInfo wii
+ && wii.usingLowResIcon()
+ && wii.itemType == Favorites.ITEM_TYPE_APPLICATION
&& verifiers.stream().anyMatch(it -> it.isItemInPreview(info.rank))) {
- mIconCache.getTitleAndIcon(info, false);
+ mIconCache.getTitleAndIcon(wii, false);
+ } else if (info instanceof AppPairInfo api) {
+ api.fetchHiResIconsIfNeeded(mIconCache);
}
}
}
@@ -788,7 +789,7 @@
FolderNameInfos suggestionInfos = new FolderNameInfos();
CollectionInfo info = mBgDataModel.collections.valueAt(i);
if (info instanceof FolderInfo fi && fi.suggestedFolderNames == null) {
- provider.getSuggestedFolderName(mApp.getContext(), fi.getContents(),
+ provider.getSuggestedFolderName(mApp.getContext(), fi.getAppContents(),
suggestionInfos);
fi.suggestedFolderNames = suggestionInfos;
}
diff --git a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
index ba612cc..fd38af3 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -32,6 +32,7 @@
import com.android.launcher3.LauncherSettings.Favorites
import com.android.launcher3.Utilities
import com.android.launcher3.backuprestore.LauncherRestoreEventLogger.RestoreError
+import com.android.launcher3.config.FeatureFlags
import com.android.launcher3.logging.FileLog
import com.android.launcher3.model.data.AppPairInfo
import com.android.launcher3.model.data.FolderInfo
@@ -373,10 +374,16 @@
// If we generated a placeholder Folder before this point, it may need to be replaced with
// an app pair.
if (c.itemType == Favorites.ITEM_TYPE_APP_PAIR && collection is FolderInfo) {
+ if (!FeatureFlags.enableAppPairs()) {
+ // If app pairs are not enabled, stop loading.
+ Log.e(TAG, "app pairs flag is off, did not load app pair")
+ return
+ }
+
val folderInfo: FolderInfo = collection
val newAppPair = AppPairInfo()
// Move the placeholder's contents over to the new app pair.
- folderInfo.contents.forEach(newAppPair::add)
+ folderInfo.getContents().forEach(newAppPair::add)
collection = newAppPair
// Remove the placeholder and add the app pair into the data model.
bgDataModel.collections.remove(c.id)
diff --git a/src/com/android/launcher3/model/data/AppPairInfo.kt b/src/com/android/launcher3/model/data/AppPairInfo.kt
index 4081316..fad365c 100644
--- a/src/com/android/launcher3/model/data/AppPairInfo.kt
+++ b/src/com/android/launcher3/model/data/AppPairInfo.kt
@@ -18,11 +18,15 @@
import android.content.Context
import com.android.launcher3.LauncherSettings
+import com.android.launcher3.R
+import com.android.launcher3.icons.IconCache
import com.android.launcher3.logger.LauncherAtom
import com.android.launcher3.views.ActivityContext
/** A type of app collection that launches multiple apps into split screen. */
class AppPairInfo() : CollectionInfo() {
+ private var contents: ArrayList<WorkspaceItemInfo> = ArrayList()
+
init {
itemType = LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR
}
@@ -33,11 +37,28 @@
add(app2)
}
- /** Adds an element to the contents array. */
- override fun add(item: WorkspaceItemInfo) {
+ /** Creates a new AppPairInfo that is a copy of the provided one. */
+ constructor(appPairInfo: AppPairInfo) : this() {
+ contents = appPairInfo.contents.clone() as ArrayList<WorkspaceItemInfo>
+ copyFrom(appPairInfo)
+ }
+
+ /** Adds an element to the contents ArrayList. */
+ override fun add(item: ItemInfo) {
+ if (item !is WorkspaceItemInfo) {
+ throw RuntimeException("tried to add an illegal type into an app pair")
+ }
+
contents.add(item)
}
+ /** Returns the app pair's member apps as an ArrayList of [ItemInfo]. */
+ override fun getContents(): ArrayList<ItemInfo> =
+ ArrayList(contents.stream().map { it as ItemInfo }.toList())
+
+ /** Returns the app pair's member apps as an ArrayList of [WorkspaceItemInfo]. */
+ override fun getAppContents(): ArrayList<WorkspaceItemInfo> = contents
+
/** Returns the first app in the pair. */
fun getFirstApp() = contents[0]
@@ -50,7 +71,34 @@
/** Checks if the app pair is launchable at the current screen size. */
fun isLaunchable(context: Context) =
(ActivityContext.lookupContext(context) as ActivityContext).getDeviceProfile().isTablet ||
- noneMatch { it.hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE) }
+ getAppContents().stream().noneMatch {
+ it.hasStatusFlag(WorkspaceItemInfo.FLAG_NON_RESIZEABLE)
+ }
+
+ /** Fetches high-res icons for member apps if needed. */
+ fun fetchHiResIconsIfNeeded(iconCache: IconCache) {
+ getAppContents().stream().filter(ItemInfoWithIcon::usingLowResIcon).forEach { member ->
+ iconCache.getTitleAndIcon(member, false)
+ }
+ }
+
+ /**
+ * App pairs will draw as "disabled" if either of the following is true:
+ * 1) One of the member WorkspaceItemInfos is disabled (i.e. the app software itself is paused
+ * or can't be launched for some other reason).
+ * 2) One of the member apps can't be launched due to screen size requirements.
+ */
+ fun shouldDrawAsDisabled(context: Context): Boolean {
+ return isDisabled || !isLaunchable(context)
+ }
+
+ /** Generates a default title for the app pair and sets it. */
+ fun generateTitle(context: Context): CharSequence? {
+ val app1: CharSequence? = getFirstApp().title
+ val app2: CharSequence? = getSecondApp().title
+ title = context.getString(R.string.app_pair_default_title, app1, app2)
+ return title
+ }
/** Generates an ItemInfo for logging. */
override fun buildProto(cInfo: CollectionInfo?): LauncherAtom.ItemInfo {
diff --git a/src/com/android/launcher3/model/data/CollectionInfo.kt b/src/com/android/launcher3/model/data/CollectionInfo.kt
index 2b865a5..4f5e12f 100644
--- a/src/com/android/launcher3/model/data/CollectionInfo.kt
+++ b/src/com/android/launcher3/model/data/CollectionInfo.kt
@@ -22,19 +22,21 @@
import java.util.function.Predicate
abstract class CollectionInfo : ItemInfo() {
- var contents: ArrayList<WorkspaceItemInfo> = ArrayList()
+ /** Adds an ItemInfo to the collection. Throws if given an illegal type. */
+ abstract fun add(item: ItemInfo)
- abstract fun add(item: WorkspaceItemInfo)
+ /** Returns the collection's contents as an ArrayList of [ItemInfo]. */
+ abstract fun getContents(): ArrayList<ItemInfo>
+
+ /**
+ * Returns the collection's contents as an ArrayList of [WorkspaceItemInfo]. Does not include
+ * other collection [ItemInfo]s that are inside this collection; rather, it should collect
+ * *their* contents and adds them to the ArrayList.
+ */
+ abstract fun getAppContents(): ArrayList<WorkspaceItemInfo>
/** Convenience function. Checks contents to see if any match a given predicate. */
- fun anyMatch(matcher: Predicate<in WorkspaceItemInfo>): Boolean {
- return contents.stream().anyMatch(matcher)
- }
-
- /** Convenience function. Returns true if none of the contents match a given predicate. */
- fun noneMatch(matcher: Predicate<in WorkspaceItemInfo>): Boolean {
- return contents.stream().noneMatch(matcher)
- }
+ fun anyMatch(matcher: Predicate<ItemInfo>) = getContents().stream().anyMatch(matcher)
override fun onAddToDatabase(writer: ContentWriter) {
super.onAddToDatabase(writer)
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index 1bbb2fe..56996ef 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -29,6 +29,7 @@
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
+import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderNameInfos;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logger.LauncherAtom.Attribute;
@@ -98,14 +99,20 @@
public FolderNameInfos suggestedFolderNames;
+ /**
+ * The apps and shortcuts
+ */
+ private final ArrayList<ItemInfo> contents = new ArrayList<>();
+
private ArrayList<FolderListener> mListeners = new ArrayList<>();
public FolderInfo() {
itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
}
- /** Adds a app or shortcut to the contents array without animation. */
- public void add(@NonNull WorkspaceItemInfo item) {
+ /** Adds a app or shortcut to the contents ArrayList without animation. */
+ @Override
+ public void add(@NonNull ItemInfo item) {
add(item, false /* animate */);
}
@@ -114,14 +121,18 @@
*
* @param item
*/
- public void add(WorkspaceItemInfo item, boolean animate) {
+ public void add(ItemInfo item, boolean animate) {
add(item, getContents().size(), animate);
}
/**
* Add an app or shortcut for a specified rank.
*/
- public void add(WorkspaceItemInfo item, int rank, boolean animate) {
+ public void add(ItemInfo item, int rank, boolean animate) {
+ if (!Folder.willAccept(item)) {
+ throw new RuntimeException("tried to add an illegal type into a folder");
+ }
+
rank = Utilities.boundToRange(rank, 0, getContents().size());
getContents().add(rank, item);
for (int i = 0; i < mListeners.size(); i++) {
@@ -135,21 +146,49 @@
*
* @param item
*/
- public void remove(WorkspaceItemInfo item, boolean animate) {
+ public void remove(ItemInfo item, boolean animate) {
removeAll(Collections.singletonList(item), animate);
}
/**
* Remove all matching app or shortcut. Does not change the DB.
*/
- public void removeAll(List<WorkspaceItemInfo> items, boolean animate) {
- getContents().removeAll(items);
+ public void removeAll(List<ItemInfo> items, boolean animate) {
+ contents.removeAll(items);
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onRemove(items);
}
itemsChanged(animate);
}
+ /**
+ * Returns the folder's contents as an ArrayList of {@link ItemInfo}. Includes
+ * {@link WorkspaceItemInfo} and {@link AppPairInfo}s.
+ */
+ @NonNull
+ @Override
+ public ArrayList<ItemInfo> getContents() {
+ return contents;
+ }
+
+ /**
+ * Returns the folder's contents as an ArrayList of {@link WorkspaceItemInfo}. Note: Does not
+ * return any {@link AppPairInfo}s contained in the folder, instead collects *their* contents
+ * and adds them to the ArrayList.
+ */
+ @Override
+ public ArrayList<WorkspaceItemInfo> getAppContents() {
+ ArrayList<WorkspaceItemInfo> workspaceItemInfos = new ArrayList<>();
+ for (ItemInfo item : contents) {
+ if (item instanceof WorkspaceItemInfo wii) {
+ workspaceItemInfos.add(wii);
+ } else if (item instanceof AppPairInfo api) {
+ workspaceItemInfos.addAll(api.getAppContents());
+ }
+ }
+ return workspaceItemInfos;
+ }
+
@Override
public void onAddToDatabase(@NonNull ContentWriter writer) {
super.onAddToDatabase(writer);
@@ -171,8 +210,8 @@
}
public interface FolderListener {
- void onAdd(WorkspaceItemInfo item, int rank);
- void onRemove(List<WorkspaceItemInfo> item);
+ void onAdd(ItemInfo item, int rank);
+ void onRemove(List<ItemInfo> item);
void onItemsChanged(boolean animate);
}
@@ -263,10 +302,17 @@
public ItemInfo makeShallowCopy() {
FolderInfo folderInfo = new FolderInfo();
folderInfo.copyFrom(this);
- folderInfo.setContents(this.getContents());
return folderInfo;
}
+ @Override
+ public void copyFrom(@NonNull ItemInfo info) {
+ super.copyFrom(info);
+ if (info instanceof FolderInfo fi) {
+ contents.addAll(fi.getContents());
+ }
+ }
+
/**
* Returns index of the accepted suggestion.
*/
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index de24be7..816d5e9 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -158,20 +158,27 @@
? R.string.app_pair_needs_unfold
: R.string.app_pair_unlaunchable_at_screen_size,
Toast.LENGTH_SHORT).show();
+ return;
} else if (appPairIcon.getInfo().isDisabled()) {
WorkspaceItemInfo app1 = appPairIcon.getInfo().getFirstApp();
WorkspaceItemInfo app2 = appPairIcon.getInfo().getSecondApp();
// Show the user why the app pair is disabled.
- if (app1.isDisabled() && !handleDisabledItemClicked(app1, launcher)) {
- // If handleDisabledItemClicked() did not handle the error message, we initiate an
- // app launch so Framework can tell the user why the app is suspended.
- onClickAppShortcut(v, app1, launcher);
- } else if (app2.isDisabled() && !handleDisabledItemClicked(app2, launcher)) {
- onClickAppShortcut(v, app2, launcher);
+ if (app1.isDisabled() && app2.isDisabled()) {
+ // Both apps are disabled, show "app pair is not available" toast.
+ Toast.makeText(launcher, R.string.app_pair_not_available, Toast.LENGTH_SHORT)
+ .show();
+ return;
+ } else if ((app1.isDisabled() && handleDisabledItemClicked(app1, launcher))
+ || (app2.isDisabled() && handleDisabledItemClicked(app2, launcher))) {
+ // Only one is disabled, and handleDisabledItemClicked() will show a toast, so we
+ // are done.
+ return;
}
- } else {
- launcher.launchAppPair(appPairIcon);
}
+
+ // Either the app pair is not disabled, or it is a disabled state that can be handled by
+ // framework directly (e.g. one app is paused), so go ahead and launch.
+ launcher.launchAppPair(appPairIcon);
}
/**
diff --git a/tests/src/com/android/launcher3/folder/PreviewItemManagerTest.kt b/tests/src/com/android/launcher3/folder/PreviewItemManagerTest.kt
index 3a1883c..da14425 100644
--- a/tests/src/com/android/launcher3/folder/PreviewItemManagerTest.kt
+++ b/tests/src/com/android/launcher3/folder/PreviewItemManagerTest.kt
@@ -29,7 +29,7 @@
import com.android.launcher3.icons.FastBitmapDrawable
import com.android.launcher3.icons.UserBadgeDrawable
import com.android.launcher3.model.data.FolderInfo
-import com.android.launcher3.model.data.WorkspaceItemInfo
+import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.util.ActivityContextWrapper
import com.android.launcher3.util.FlagOp
import com.android.launcher3.util.LauncherLayoutBuilder
@@ -47,7 +47,7 @@
private lateinit var previewItemManager: PreviewItemManager
private lateinit var context: Context
- private lateinit var folderItems: ArrayList<WorkspaceItemInfo>
+ private lateinit var folderItems: ArrayList<ItemInfo>
private lateinit var modelHelper: LauncherModelHelper
private lateinit var folderIcon: FolderIcon
@@ -72,15 +72,17 @@
.build()
)
.loadModelSync()
- folderItems = modelHelper.bgDataModel.collections.valueAt(0).contents
+ folderItems = modelHelper.bgDataModel.collections.valueAt(0).getContents()
folderIcon.mInfo = modelHelper.bgDataModel.collections.valueAt(0) as FolderInfo
- folderIcon.mInfo.contents = folderItems
+ folderIcon.mInfo.getContents().addAll(folderItems)
+ // Use getAppContents() to "cast" contents to WorkspaceItemInfo so we can set bitmaps
+ val folderApps = modelHelper.bgDataModel.collections.valueAt(0).getAppContents()
// Set first icon to be themed.
- folderItems[0]
+ folderApps[0]
.bitmap
.setMonoIcon(
- folderItems[0].bitmap.icon,
+ folderApps[0].bitmap.icon,
BaseIconFactory(
context,
context.resources.configuration.densityDpi,
@@ -89,7 +91,7 @@
)
// Set second icon to be non-themed.
- folderItems[1]
+ folderApps[1]
.bitmap
.setMonoIcon(
null,
@@ -101,23 +103,21 @@
)
// Set third icon to be themed with badge.
- folderItems[2]
+ folderApps[2]
.bitmap
.setMonoIcon(
- folderItems[2].bitmap.icon,
+ folderApps[2].bitmap.icon,
BaseIconFactory(
context,
context.resources.configuration.densityDpi,
previewItemManager.mIconSize
)
)
- folderItems[2].bitmap =
- folderItems[2].bitmap.withFlags(profileFlagOp(UserIconInfo.TYPE_WORK))
+ folderApps[2].bitmap = folderApps[2].bitmap.withFlags(profileFlagOp(UserIconInfo.TYPE_WORK))
// Set fourth icon to be non-themed with badge.
- folderItems[3].bitmap =
- folderItems[3].bitmap.withFlags(profileFlagOp(UserIconInfo.TYPE_WORK))
- folderItems[3]
+ folderApps[3].bitmap = folderApps[3].bitmap.withFlags(profileFlagOp(UserIconInfo.TYPE_WORK))
+ folderApps[3]
.bitmap
.setMonoIcon(
null,
diff --git a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
index abb0c39..d3a6355 100644
--- a/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
+++ b/tests/src/com/android/launcher3/model/CacheDataUpdatedTaskTest.java
@@ -160,6 +160,6 @@
}
private List<WorkspaceItemInfo> allItems() {
- return ((FolderInfo) mModelHelper.getBgDataModel().itemsIdMap.get(1)).getContents();
+ return ((FolderInfo) mModelHelper.getBgDataModel().itemsIdMap.get(1)).getAppContents();
}
}
diff --git a/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt b/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt
index ed587a1..2e209a4 100644
--- a/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt
+++ b/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt
@@ -168,8 +168,8 @@
val collections = modelHelper.getBgDataModel().collections
assertThat(collections.size()).isEqualTo(1)
- assertThat(collections.valueAt(0).contents.size).isEqualTo(itemCount)
- return collections.valueAt(0).contents
+ assertThat(collections.valueAt(0).getAppContents().size).isEqualTo(itemCount)
+ return collections.valueAt(0).getAppContents()
}
private fun verifyHighRes(items: ArrayList<WorkspaceItemInfo>, vararg indices: Int) {
diff --git a/tests/src/com/android/launcher3/util/ItemInflaterTest.kt b/tests/src/com/android/launcher3/util/ItemInflaterTest.kt
index 0065527..dae09bb 100644
--- a/tests/src/com/android/launcher3/util/ItemInflaterTest.kt
+++ b/tests/src/com/android/launcher3/util/ItemInflaterTest.kt
@@ -139,9 +139,9 @@
@Test
fun test_folder_inflated_on_UI() {
val itemInfo = FolderInfo()
- itemInfo.contents.add(workspaceItemInfo())
- itemInfo.contents.add(workspaceItemInfo())
- itemInfo.contents.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
val view =
MAIN_EXECUTOR.submit(Callable { underTest.inflateItem(itemInfo, modelWriter) }).get()
@@ -155,9 +155,9 @@
setFlagsRule.enableFlags(Flags.FLAG_ENABLE_WORKSPACE_INFLATION)
val itemInfo = FolderInfo()
- itemInfo.contents.add(workspaceItemInfo())
- itemInfo.contents.add(workspaceItemInfo())
- itemInfo.contents.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
val view =
VIEW_PREINFLATION_EXECUTOR.submit(
@@ -173,8 +173,8 @@
fun test_app_pair_inflated_on_UI() {
val itemInfo = AppPairInfo()
itemInfo.itemType = ITEM_TYPE_APP_PAIR
- itemInfo.contents.add(workspaceItemInfo())
- itemInfo.contents.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
val view =
MAIN_EXECUTOR.submit(Callable { underTest.inflateItem(itemInfo, modelWriter) }).get()
@@ -189,8 +189,8 @@
val itemInfo = AppPairInfo()
itemInfo.itemType = ITEM_TYPE_APP_PAIR
- itemInfo.contents.add(workspaceItemInfo())
- itemInfo.contents.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
+ itemInfo.add(workspaceItemInfo())
val view =
VIEW_PREINFLATION_EXECUTOR.submit(