Merge "Allow app pairs in folders" 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/util/AppPairsController.java b/quickstep/src/com/android/quickstep/util/AppPairsController.java
index f4da867..59bf105 100644
--- a/quickstep/src/com/android/quickstep/util/AppPairsController.java
+++ b/quickstep/src/com/android/quickstep/util/AppPairsController.java
@@ -153,7 +153,7 @@
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());
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/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/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index ce3c55a..e80156c 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -17,7 +17,7 @@
package com.android.launcher3;
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;
@@ -1873,12 +1873,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 +1922,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);
@@ -3314,7 +3311,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 +3378,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..8ce1c19 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;
@@ -180,9 +182,17 @@
}
/**
+ * 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)) {
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..e2c2670 100644
--- a/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
+++ b/src/com/android/launcher3/apppairs/AppPairIconDrawingParams.kt
@@ -77,22 +77,29 @@
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()
- }
+ bgColor = getBgColorForContainer(container)
}
/** Checks the device orientation and updates isLeftRightSplit accordingly. */
fun updateOrientation(dp: DeviceProfile) {
isLeftRightSplit = dp.isLeftRightSplit
}
+
+ private fun getBgColorForContainer(container: Int): Int {
+ val color: Int
+ if (container == DISPLAY_FOLDER) {
+ val ta =
+ context.theme.obtainStyledAttributes(
+ intArrayOf(R.attr.materialColorSurfaceContainerLowest)
+ )
+ color = ta.getColor(0, 0)
+ ta.recycle()
+ } else {
+ val ta = context.theme.obtainStyledAttributes(R.styleable.FolderIconPreview)
+ color = ta.getColor(R.styleable.FolderIconPreview_folderPreviewColor, 0)
+ ta.recycle()
+ }
+
+ return color
+ }
}
diff --git a/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt b/src/com/android/launcher3/apppairs/AppPairIconGraphic.kt
index a3a1cfc..86ee0c0 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
@@ -52,7 +51,10 @@
* 2) One of the member apps can't be launched due to screen size requirements.
*/
@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)
@@ -81,7 +83,7 @@
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,12 +118,6 @@
redraw()
}
- /** Updates the icon drawable and redraws it */
- fun redraw() {
- drawable = composeDrawable(parentIcon.info, drawParams)
- invalidate()
- }
-
/**
* Gets this icon graphic's visual bounds, with respect to the parent icon's coordinate system.
*/
@@ -136,6 +132,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..1093753 100644
--- a/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
+++ b/src/com/android/launcher3/model/WorkspaceItemProcessor.kt
@@ -376,7 +376,7 @@
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..a56ee8e 100644
--- a/src/com/android/launcher3/model/data/AppPairInfo.kt
+++ b/src/com/android/launcher3/model/data/AppPairInfo.kt
@@ -18,11 +18,14 @@
import android.content.Context
import com.android.launcher3.LauncherSettings
+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 +36,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 +70,9 @@
/** 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)
+ }
/** Generates an ItemInfo for logging. */
override fun buildProto(cInfo: CollectionInfo?): LauncherAtom.ItemInfo {
@@ -62,4 +84,11 @@
.setContainerInfo(getContainerInfo())
.build()
}
+
+ /** Fetches high-res icons for member apps if needed. */
+ fun fetchHiResIconsIfNeeded(iconCache: IconCache) {
+ getAppContents().stream().filter(ItemInfoWithIcon::usingLowResIcon).forEach { member ->
+ iconCache.getTitleAndIcon(member, false)
+ }
+ }
}
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/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(