diff --git a/lawnchair/res/layout/all_apps_folder_application.xml b/lawnchair/res/layout/all_apps_folder_application.xml
new file mode 100644
index 0000000000..8e02012883
--- /dev/null
+++ b/lawnchair/res/layout/all_apps_folder_application.xml
@@ -0,0 +1,23 @@
+
+
+
diff --git a/lawnchair/res/layout/all_apps_folder_icon.xml b/lawnchair/res/layout/all_apps_folder_icon.xml
new file mode 100644
index 0000000000..47fb1415af
--- /dev/null
+++ b/lawnchair/res/layout/all_apps_folder_icon.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
diff --git a/lawnchair/res/values/strings.xml b/lawnchair/res/values/strings.xml
index ec328e3f9a..abcedb5c28 100644
--- a/lawnchair/res/values/strings.xml
+++ b/lawnchair/res/values/strings.xml
@@ -59,6 +59,7 @@
General "words" used throughout Lawnchair
-->
+ Others
Dynamic
@@ -90,6 +91,9 @@
Wallpapers
+ Caddy (Beta)
+ Caddy
+
To lock your phone when performing a gesture, and to open Recents via gesture, Lawnchair requires accessibility access.\n\nLawnchair doesn\'t watch any user action, though the privilege to do so is required for all accessibility services. Lawnchair discards any event sent by the system.\n\nIn order to lock your phone, or to open Recents, Lawnchair uses the performGlobalAction Accessibility service.
diff --git a/lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt b/lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt
index e9ccdd6f5f..1b50bf1756 100644
--- a/lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt
+++ b/lawnchair/src/app/lawnchair/allapps/LawnchairAlphabeticalAppsList.kt
@@ -4,19 +4,23 @@ import android.content.Context
import android.util.Log
import androidx.lifecycle.lifecycleScope
import app.lawnchair.launcher
+import app.lawnchair.preferences.PreferenceManager
import app.lawnchair.preferences2.PreferenceManager2
+import app.lawnchair.util.categorizeApps
import com.android.launcher3.allapps.AllAppsStore
import com.android.launcher3.allapps.AlphabeticalAppsList
+import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem
import com.android.launcher3.allapps.PrivateProfileManager
import com.android.launcher3.allapps.WorkProfileManager
import com.android.launcher3.model.data.AppInfo
+import com.android.launcher3.model.data.FolderInfo
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.views.ActivityContext
import com.patrykmichalik.opto.core.onEach
import java.util.function.Predicate
class LawnchairAlphabeticalAppsList(
- context: T,
+ private val context: T,
appsStore: AllAppsStore,
workProfileManager: WorkProfileManager?,
privateProfileManager: PrivateProfileManager?,
@@ -24,11 +28,11 @@ class LawnchairAlphabeticalAppsList(
where T : Context, T : ActivityContext {
private var hiddenApps: Set = setOf()
- private val prefs = PreferenceManager2.getInstance(context)
-
+ private val prefs2 = PreferenceManager2.getInstance(context)
+ private val prefs = PreferenceManager.getInstance(context)
init {
try {
- prefs.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
+ prefs2.hiddenApps.onEach(launchIn = context.launcher.lifecycleScope) {
hiddenApps = it
onAppsUpdated()
}
@@ -45,4 +49,35 @@ class LawnchairAlphabeticalAppsList(
}
onAppsUpdated()
}
+
+ override fun addAppsWithSections(appList: List?, startPosition: Int): Int {
+ if (appList.isNullOrEmpty()) return startPosition
+ val drawerListDefault = prefs.drawerList.get()
+ var position = startPosition
+
+ if (!drawerListDefault) {
+ val categorizedApps = categorizeApps(context, appList)
+
+ if (categorizedApps.isNotEmpty()) {
+ for ((category, apps) in categorizedApps) {
+ if (apps.size <= 1) {
+ val app = apps[0]
+ mAdapterItems.add(AdapterItem.asApp(app))
+ } else {
+ val folderInfo = FolderInfo()
+ folderInfo.title = category
+ for (app in apps) {
+ folderInfo.add(app)
+ }
+ mAdapterItems.add(AdapterItem.asFolder(folderInfo))
+ }
+ position++
+ }
+ }
+ } else {
+ position = super.addAppsWithSections(appList, startPosition)
+ }
+
+ return position
+ }
}
diff --git a/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt b/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt
index 1d90488d91..e791d59cac 100644
--- a/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt
+++ b/lawnchair/src/app/lawnchair/preferences/PreferenceManager.kt
@@ -115,6 +115,8 @@ class PreferenceManager private constructor(private val context: Context) :
val wallpaperBlur = IntPref("pref_wallpaperBlur", 25, recreate)
val wallpaperBlurFactorThreshold = FloatPref("pref_wallpaperBlurFactor", 3.0F, recreate)
+ val drawerList = BoolPref("pref_drawerList", true, recreate)
+
val recentsActionScreenshot = BoolPref("pref_recentsActionScreenshot", !isOnePlusStock)
val recentsActionShare = BoolPref("pref_recentsActionShare", isOnePlusStock)
val recentsActionLens = BoolPref("pref_recentsActionLens", true)
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerPreferences.kt b/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerPreferences.kt
index c91684dfc3..795adeef01 100644
--- a/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerPreferences.kt
+++ b/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerPreferences.kt
@@ -53,6 +53,7 @@ fun AppDrawerPreferences(
backArrowVisible = !LocalIsExpandedScreen.current,
modifier = modifier,
) {
+ AppDrawerSettings()
PreferenceGroup(heading = stringResource(id = R.string.general_label)) {
ColorPreference(preference = prefs2.appDrawerBackgroundColor)
SliderPreference(
diff --git a/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerSettings.kt b/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerSettings.kt
new file mode 100644
index 0000000000..717657ddcc
--- /dev/null
+++ b/lawnchair/src/app/lawnchair/ui/preferences/destinations/AppDrawerSettings.kt
@@ -0,0 +1,186 @@
+package app.lawnchair.ui.preferences.destinations
+
+import androidx.compose.animation.animateColorAsState
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.width
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import app.lawnchair.preferences.preferenceManager
+import com.android.launcher3.R
+
+@Composable
+fun AppDrawerSettings(
+ modifier: Modifier = Modifier,
+) {
+ val prefs = preferenceManager()
+ val context = LocalContext.current
+ val resources = context.resources
+ var selectedOption by remember { mutableStateOf(prefs.drawerList.get()) }
+
+ Row(
+ modifier = modifier
+ .fillMaxWidth()
+ .background(MaterialTheme.colorScheme.background)
+ .padding(16.dp),
+ horizontalArrangement = Arrangement.SpaceBetween,
+ ) {
+ ButtonSection(
+ modifier = Modifier,
+ label = resources.getString(R.string.feed_default),
+ isSelected = selectedOption,
+ onClick = {
+ selectedOption = true
+ prefs.drawerList.set(true)
+ },
+ gridLayout = {
+ Column(modifier = Modifier, horizontalAlignment = Alignment.CenterHorizontally) {
+ Row(
+ modifier = Modifier,
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ ) {
+ repeat(4) {
+ Box(
+ modifier = Modifier
+ .size(16.dp)
+ .background(
+ MaterialTheme.colorScheme.surfaceVariant,
+ CircleShape,
+ ),
+ )
+ }
+ }
+ }
+ },
+ )
+
+ Spacer(modifier = Modifier.width(16.dp))
+
+ ButtonSection(
+ modifier = Modifier,
+ label = resources.getString(R.string.caddy_beta),
+ isSelected = !selectedOption,
+ onClick = {
+ selectedOption = false
+ prefs.drawerList.set(false)
+ },
+ gridLayout = {
+ Column(modifier = Modifier, horizontalAlignment = Alignment.CenterHorizontally) {
+ Row(
+ modifier = Modifier,
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ ) {
+ repeat(2) {
+ Box(
+ modifier = Modifier
+ .size(16.dp)
+ .background(
+ MaterialTheme.colorScheme.surfaceVariant,
+ CircleShape,
+ ),
+ )
+ }
+ }
+ Spacer(modifier = Modifier.height(8.dp))
+ Row(
+ modifier = Modifier,
+ horizontalArrangement = Arrangement.spacedBy(8.dp),
+ ) {
+ repeat(2) {
+ Box(
+ modifier = Modifier
+ .size(16.dp)
+ .background(
+ MaterialTheme.colorScheme.surfaceVariant,
+ CircleShape,
+ ),
+ )
+ }
+ }
+ }
+ },
+ )
+ }
+}
+
+@Composable
+fun ButtonSection(
+ label: String,
+ isSelected: Boolean,
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+ gridLayout: @Composable () -> Unit,
+) {
+ val backgroundColor by animateColorAsState(
+ targetValue = if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.surfaceContainer,
+ animationSpec = tween(durationMillis = 300),
+ )
+
+ val textColor by animateColorAsState(
+ targetValue = if (isSelected) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface,
+ animationSpec = tween(durationMillis = 300),
+ )
+
+ Box(
+ modifier = modifier
+ .size(160.dp, 120.dp)
+ .background(backgroundColor, RoundedCornerShape(16.dp))
+ .clickable { onClick() }
+ .padding(12.dp),
+ ) {
+ Column(
+ modifier = Modifier.fillMaxSize(),
+ verticalArrangement = Arrangement.SpaceBetween,
+ horizontalAlignment = Alignment.CenterHorizontally,
+ ) {
+ Box(
+ modifier = Modifier
+ .height(24.dp)
+ .fillMaxWidth(0.8f)
+ .background(MaterialTheme.colorScheme.surfaceVariant, RoundedCornerShape(8.dp)),
+ )
+
+ gridLayout()
+
+ Text(
+ modifier = Modifier,
+ text = label,
+ color = textColor,
+ fontSize = 14.sp,
+ )
+ }
+ }
+}
+
+@Preview(showBackground = true)
+@Composable
+private fun PreviewToggleSelectionUI() {
+ Surface {
+ AppDrawerSettings()
+ }
+}
diff --git a/lawnchair/src/app/lawnchair/util/AppsList.kt b/lawnchair/src/app/lawnchair/util/AppsList.kt
index dca4b0c945..2bc123a96f 100644
--- a/lawnchair/src/app/lawnchair/util/AppsList.kt
+++ b/lawnchair/src/app/lawnchair/util/AppsList.kt
@@ -17,6 +17,7 @@
package app.lawnchair.util
import android.content.Context
+import android.content.pm.ApplicationInfo
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.graphics.Bitmap
@@ -29,6 +30,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import com.android.launcher3.AppFilter
import com.android.launcher3.LauncherAppState
+import com.android.launcher3.R
import com.android.launcher3.Utilities
import com.android.launcher3.model.data.AppInfo
import com.android.launcher3.pm.UserCache
@@ -76,3 +78,22 @@ class App(context: Context, private val info: LauncherActivityInfo) {
}
val appComparator: Comparator = comparing { it.label.lowercase(Locale.getDefault()) }
+val packageInfoCache = mutableMapOf()
+
+fun categorizeApps(context: Context, appList: List?): Map> {
+ val categories = mutableMapOf>()
+ val validAppList = appList?.filterNotNull() ?: emptyList()
+ for (appInfo in validAppList) {
+ val packageName = appInfo.targetPackage!!
+ val applicationInfo = packageInfoCache.getOrPut(packageName) {
+ context.packageManager.getApplicationInfo(packageName, 0)
+ }
+ val categoryTitle = ApplicationInfo.getCategoryTitle(context, applicationInfo.category) ?: context.resources.getString(R.string.others_category_label)
+ val categoryList = categories.getOrPut(categoryTitle.toString()) { mutableListOf() }
+ if (!categoryList.contains(appInfo)) {
+ categoryList.add(appInfo)
+ }
+ }
+
+ return categories.toSortedMap().mapValues { it.value }
+}
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index be8b2e13d9..c46b7c7e3e 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -94,6 +94,7 @@
+
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index a6dc0da54a..e081442067 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -116,6 +116,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
public static final int DISPLAY_PREDICTION_ROW = 8;
public static final int DISPLAY_SEARCH_RESULT_APP_ROW = 9;
+ private static final int DISPLAY_DRAWER_FOLDER = 10;
+
private static final float MIN_LETTER_SPACING = -0.05f;
private static final int MAX_SEARCH_LOOP_COUNT = 20;
private static final Character NEW_LINE = '\n';
@@ -250,7 +252,7 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
defaultIconSize = mDeviceProfile.iconSizePx;
setCenterVertically(mDeviceProfile.iconCenterVertically);
} else if (mDisplay == DISPLAY_ALL_APPS || mDisplay == DISPLAY_PREDICTION_ROW
- || mDisplay == DISPLAY_SEARCH_RESULT_APP_ROW) {
+ || mDisplay == DISPLAY_SEARCH_RESULT_APP_ROW || mDisplay == DISPLAY_DRAWER_FOLDER) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, mDeviceProfile.allAppsIconTextSizePx);
setCompoundDrawablePadding(mDeviceProfile.allAppsIconDrawablePaddingPx);
defaultIconSize = mDeviceProfile.allAppsIconSizePx;
diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
index 4b2b5a861f..1c4acf8fc0 100644
--- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java
@@ -92,7 +92,7 @@ public class AlphabeticalAppsList implement
// The number of results in current adapter
private int mAccessibilityResultsCount = 0;
// The current set of adapter items
- private final ArrayList mAdapterItems = new ArrayList<>();
+ protected final ArrayList mAdapterItems = new ArrayList<>();
// The set of sections that we allow fast-scrolling to (includes non-merged
// sections)
private final List mFastScrollerSections = new ArrayList<>();
@@ -399,7 +399,7 @@ public class AlphabeticalAppsList implement
return position;
}
- private int addAppsWithSections(List appList, int startPosition) {
+ protected int addAppsWithSections(List appList, int startPosition) {
String lastSectionName = null;
boolean hasPrivateApps = false;
int position = startPosition;
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
index a5c54b41ad..c3af72bae6 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsAdapter.java
@@ -32,6 +32,7 @@ import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
+import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
@@ -44,7 +45,9 @@ import com.android.launcher3.LauncherPrefs;
import com.android.launcher3.R;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
@@ -74,11 +77,13 @@ public abstract class BaseAllAppsAdapter ex
public static final int VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER = 1 << 7;
public static final int VIEW_TYPE_WORK_EDU_CARD = 1 << 8;
- public static final int NEXT_ID = 8;
+ public static final int VIEW_TYPE_FOLDER = 1 << 9;
+
+ public static final int NEXT_ID = 10;
// Common view type masks
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
- public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
+ public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON | VIEW_TYPE_FOLDER;
public static final int VIEW_TYPE_MASK_PRIVATE_SPACE_HEADER = VIEW_TYPE_PRIVATE_SPACE_HEADER;
public static final int VIEW_TYPE_MASK_PRIVATE_SPACE_SYS_APPS_DIVIDER = VIEW_TYPE_PRIVATE_SPACE_SYS_APPS_DIVIDER;
@@ -115,6 +120,8 @@ public abstract class BaseAllAppsAdapter ex
public int rowAppIndex;
// The associated ItemInfoWithIcon for the item
public AppInfo itemInfo = new AppInfo();
+
+ public FolderInfo folderInfo = new FolderInfo();
// Private App Decorator
public SectionDecorationInfo decorationInfo = null;
@@ -131,6 +138,12 @@ public abstract class BaseAllAppsAdapter ex
item.itemInfo = appInfo;
return item;
}
+
+ public static AdapterItem asFolder(FolderInfo folderInfo) {
+ AdapterItem item = new AdapterItem(VIEW_TYPE_FOLDER);
+ item.folderInfo = folderInfo;
+ return item;
+ }
public static AdapterItem asAppWithDecorationInfo(AppInfo appInfo,
SectionDecorationInfo decorationInfo) {
@@ -140,7 +153,7 @@ public abstract class BaseAllAppsAdapter ex
}
protected boolean isCountedForAccessibility() {
- return viewType == VIEW_TYPE_ICON;
+ return viewType == VIEW_TYPE_ICON || viewType == VIEW_TYPE_FOLDER;
}
/**
@@ -257,6 +270,12 @@ public abstract class BaseAllAppsAdapter ex
case VIEW_TYPE_PRIVATE_SPACE_HEADER:
return new ViewHolder(mLayoutInflater.inflate(
R.layout.private_space_header, parent, false));
+ case VIEW_TYPE_FOLDER:
+ FrameLayout fl = new FrameLayout(mActivityContext);
+ ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ return new ViewHolder(fl);
default:
if (mAdapterProvider.isViewSupported(viewType)) {
return mAdapterProvider.onCreateViewHolder(mLayoutInflater, parent, viewType);
@@ -333,6 +352,13 @@ public abstract class BaseAllAppsAdapter ex
case VIEW_TYPE_WORK_EDU_CARD:
((WorkEduCard) holder.itemView).setPosition(position);
break;
+ case VIEW_TYPE_FOLDER:
+ FolderInfo folderInfo = mApps.getAdapterItems().get(position).folderInfo;
+ ViewGroup container = (ViewGroup) holder.itemView;
+ container.removeAllViews();
+ container.addView(FolderIcon.inflateFolderAndIcon(R.layout.all_apps_folder_icon, mActivityContext,
+ container, folderInfo));
+ break;
default:
if (mAdapterProvider.isViewSupported(holder.getItemViewType())) {
mAdapterProvider.onBindView(holder, position);
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 7495cdbcfb..2a37ea66dc 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -403,6 +403,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
if (dragObject.dragSource != this) {
return;
}
+ if (isInAppDrawer()) close(true);
+
mContent.removeItem(mCurrentDragView);
mItemsInvalidated = true;
@@ -415,6 +417,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mItemAddedBackToSelfViaIcon = false;
}
+ public boolean isInAppDrawer() {
+ return mInfo.container == ItemInfo.NO_ID;
+ }
+
@Override
public void onDragEnd() {
if (mIsExternalDrag && mIsDragInProgress) {
@@ -583,7 +589,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
}
// In case any children didn't come across during loading, clean up the folder accordingly
mFolderIcon.post(() -> {
- if (getItemCount() <= 1) {
+ if (getItemCount() <= 1 && !isInAppDrawer()) {
replaceFolderWithFinalItem();
}
});
@@ -971,7 +977,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mRearrangeOnClose = false;
}
if (getItemCount() <= 1) {
- if (!mIsDragInProgress && !mSuppressFolderDeletion) {
+ if (!mIsDragInProgress && !mSuppressFolderDeletion && !isInAppDrawer()) {
replaceFolderWithFinalItem();
} else if (mIsDragInProgress) {
mDeleteFolderOnDropCompleted = true;
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 4c2180cecd..cc5395b7c2 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -207,7 +207,12 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
icon.mFolderName.setText(folderInfo.title);
icon.mFolderName.setCompoundDrawablePadding(0);
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) icon.mFolderName.getLayoutParams();
- lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx;
+ if (folderInfo.container == ItemInfo.NO_ID) {
+ lp.topMargin = grid.allAppsIconSizePx + grid.allAppsIconDrawablePaddingPx;
+ icon.mBackground = new PreviewBackground(activity.getDragLayer().getContext());
+ } else {
+ lp.topMargin = grid.iconSizePx + grid.iconDrawablePaddingPx;
+ }
icon.setTag(folderInfo);
icon.setOnClickListener(activity.getItemOnClickListener());
@@ -344,7 +349,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
final Launcher launcher = (Launcher) mActivity;
DragLayer dragLayer = launcher.getDragLayer();
Rect to = finalRect;
- if (to == null) {
+ if (to == null && !isInAppDrawer()) {
to = new Rect();
Workspace> workspace = launcher.getWorkspace();
// Set cellLayout and this to it's final state to compute final animation locations
@@ -434,6 +439,10 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
addItem(item);
}
}
+
+ public boolean isInAppDrawer() {
+ return mInfo.container == ItemInfo.NO_ID;
+ }
/**
* Set the suggested folder name.
@@ -772,12 +781,14 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI
}
public void clearLeaveBehindIfExists() {
+ if (isInAppDrawer()) return;
if (getParent() instanceof FolderIconParent) {
((FolderIconParent) getParent()).clearFolderLeaveBehind(this);
}
}
public void drawLeaveBehindIfExists() {
+ if (isInAppDrawer()) return;
if (getParent() instanceof FolderIconParent) {
((FolderIconParent) getParent()).drawFolderLeaveBehindForIcon(this);
}
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 6baba99f56..221613312d 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -37,6 +37,7 @@ import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Item;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
import com.android.launcher3.ShortcutAndWidgetContainer;
@@ -46,6 +47,7 @@ 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.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
@@ -225,8 +227,13 @@ public class FolderPagedView extends PagedView implements Cli
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);
+ if (mFolder.isInAppDrawer()) {
+ icon = mViewCache.getView(R.layout.all_apps_folder_application, getContext(), null);
+ ((BubbleTextView) icon).applyFromItemInfoWithIcon((ItemInfoWithIcon) item);
+ } else {
+ icon = mViewCache.getView(R.layout.folder_application, getContext(), null);
+ ((BubbleTextView) icon).applyFromWorkspaceItem((WorkspaceItemInfo) item);
+ }
}
icon.setOnClickListener(mFolder.mActivityContext.getItemOnClickListener());
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index ac0fb5be2f..cbb4d4ea7a 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -35,6 +35,7 @@ import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
+import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
@@ -47,6 +48,7 @@ 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.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
import com.android.launcher3.model.data.WorkspaceItemInfo;
@@ -463,6 +465,10 @@ public class PreviewItemManager {
AppPairIconDrawingParams appPairParams = new AppPairIconDrawingParams(mContext, DISPLAY_FOLDER);
p.drawable = AppPairIconGraphic.composeDrawable(api, appPairParams);
p.drawable.setBounds(0, 0, mIconSize, mIconSize);
+ } else if (item instanceof ItemInfoWithIcon withIcon){
+ p.drawable = withIcon.newIcon(mContext,
+ Themes.isThemedIconEnabled(mContext) ? FLAG_THEMED : 0);
+ p.drawable.setBounds(0, 0, mIconSize, mIconSize);
}
p.item = item;