mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-18 10:18:20 +00:00
Updates to app to icon animation, and turns on ADAPTIVE_ICON_WINDOW_ANIM flag.
- getFirstMatchForAppClose now only looks at the current page, since switching pages is disruptive and the animation for app closing to an icon on a different page is unclear. - Searches for package name and user id (in case of work profile app) instead of component name to handle shortcuts and trampoline activities. - Adaptive icon background drawable is now always centered - Fix crash that occurs when ADAPTIVE_ICON_WINDOW_ANIM is off. We were trying to set FolderAdaptiveIcon as the background drawable. Simplest solution is to not use folder as a search criteria when the flag is off. - Similar to DragView, FloatingIconView now uses BubbleTextView icon when adaptive icon support is not available. This handles legacy-treated apps. Bug: 123900446 Change-Id: Idaf292bb39d78db511cf2ee04a16b191454846b3
This commit is contained in:
@@ -19,9 +19,13 @@ package com.android.launcher3;
|
||||
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
|
||||
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
|
||||
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.SPRING_LOADED;
|
||||
import static com.android.launcher3.config.FeatureFlags.ADAPTIVE_ICON_WINDOW_ANIM;
|
||||
import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -34,7 +38,6 @@ import android.annotation.SuppressLint;
|
||||
import android.app.WallpaperManager;
|
||||
import android.appwidget.AppWidgetHostView;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -47,6 +50,7 @@ import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.os.UserHandle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
@@ -99,8 +103,6 @@ import com.android.launcher3.widget.PendingAppWidgetHostView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
@@ -1612,7 +1614,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
|
||||
boolean aboveShortcut = (dropOverView.getTag() instanceof ShortcutInfo);
|
||||
boolean willBecomeShortcut =
|
||||
(info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION ||
|
||||
(info.itemType == ITEM_TYPE_APPLICATION ||
|
||||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT ||
|
||||
info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);
|
||||
|
||||
@@ -2520,7 +2522,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
View view;
|
||||
|
||||
switch (info.itemType) {
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
|
||||
case ITEM_TYPE_APPLICATION:
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
|
||||
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
|
||||
if (info.container == NO_ID && info instanceof AppInfo) {
|
||||
@@ -2895,52 +2897,30 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
return layouts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all the CellLayouts on the Homescreen, starting with
|
||||
* {@param startPage}, then going outward alternating between pages prior to the startPage,
|
||||
* and then the pages after the startPage.
|
||||
* ie. if there are 5 pages [0, 1, 2, 3, 4] and startPage is 1, we return [1, 0, 2, 3, 4].
|
||||
*/
|
||||
private CellLayout[] getWorkspaceCellLayouts(int startPage) {
|
||||
int screenCount = getChildCount();
|
||||
final CellLayout[] layouts = new CellLayout[screenCount];
|
||||
int screen = 0;
|
||||
|
||||
layouts[screen] = (CellLayout) getChildAt(startPage);
|
||||
screen++;
|
||||
|
||||
for (int i = 1; screen < screenCount; ++i) {
|
||||
CellLayout prevPage = (CellLayout) getChildAt(startPage - i);
|
||||
CellLayout nextPage = (CellLayout) getChildAt(startPage + i);
|
||||
|
||||
if (prevPage != null) {
|
||||
layouts[screen] = prevPage;
|
||||
screen++;
|
||||
}
|
||||
if (nextPage != null) {
|
||||
layouts[screen] = nextPage;
|
||||
screen++;
|
||||
}
|
||||
}
|
||||
return layouts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
|
||||
* animation.
|
||||
*
|
||||
* @param component The component of the task being dismissed.
|
||||
* @param packageName The package name of the app to match.
|
||||
* @param user The user of the app to match.
|
||||
*/
|
||||
public View getFirstMatchForAppClose(ComponentName component) {
|
||||
public View getFirstMatchForAppClose(String packageName, UserHandle user) {
|
||||
final int curPage = getCurrentPage();
|
||||
final CellLayout currentPage = (CellLayout) getPageAt(curPage);
|
||||
final Workspace.ItemOperator isItemComponent = (info, view) ->
|
||||
info != null && Objects.equals(info.getTargetComponent(), component);
|
||||
final Workspace.ItemOperator isItemInFolder = (info, view) -> {
|
||||
final Workspace.ItemOperator packageAndUser = (ItemInfo info, View view) -> info != null
|
||||
&& info.getTargetComponent() != null
|
||||
&& TextUtils.equals(info.getTargetComponent().getPackageName(), packageName)
|
||||
&& info.user.equals(user);
|
||||
final Workspace.ItemOperator packageAndUserAndApp = (ItemInfo info, View view) ->
|
||||
packageAndUser.evaluate(info, view) && info.itemType == ITEM_TYPE_APPLICATION;
|
||||
final Workspace.ItemOperator packageAndUserAndShortcut = (ItemInfo info, View view) ->
|
||||
packageAndUser.evaluate(info, view) && (info.itemType == ITEM_TYPE_SHORTCUT
|
||||
|| info.itemType == ITEM_TYPE_DEEP_SHORTCUT);
|
||||
final Workspace.ItemOperator packageAndUserInFolder = (info, view) -> {
|
||||
if (info instanceof FolderInfo) {
|
||||
FolderInfo folderInfo = (FolderInfo) info;
|
||||
for (ShortcutInfo shortcutInfo : folderInfo.contents) {
|
||||
if (Objects.equals(shortcutInfo.getTargetComponent(), component)) {
|
||||
if (packageAndUser.evaluate(shortcutInfo, view)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2948,33 +2928,16 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
return false;
|
||||
};
|
||||
|
||||
CellLayout[] hotseatAndCurrentPage = new CellLayout[] { getHotseat(), currentPage };
|
||||
// First we look if the app itself is in the hotseat or on the current workspace page.
|
||||
View icon = getFirstMatch(hotseatAndCurrentPage, isItemComponent);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
// Order: App icons, shortcuts, app/shortcut in folder. Items in hotseat get returned first.
|
||||
if (ADAPTIVE_ICON_WINDOW_ANIM.get()) {
|
||||
return getFirstMatch(new CellLayout[] { getHotseat(), currentPage },
|
||||
packageAndUserAndApp, packageAndUserAndShortcut, packageAndUserInFolder);
|
||||
} else {
|
||||
// Do not use Folder as a criteria, since it'll cause a crash when trying to draw
|
||||
// FolderAdaptiveIcon as the background.
|
||||
return getFirstMatch(new CellLayout[] { getHotseat(), currentPage },
|
||||
packageAndUserAndApp, packageAndUserAndShortcut);
|
||||
}
|
||||
// Then we look if the app is in a folder on the hotseat or current workspace page.
|
||||
icon = getFirstMatch(hotseatAndCurrentPage, isItemInFolder);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
// Continue searching for the app or for a folder with the app on other pages of the
|
||||
// workspace. We skip the current page, since we already searched above.
|
||||
CellLayout[] allPages = getWorkspaceCellLayouts(curPage);
|
||||
CellLayout[] page = new CellLayout[1];
|
||||
for (int i = 1; i < allPages.length; ++i) {
|
||||
page[0] = allPages[i];
|
||||
icon = getFirstMatch(page, isItemComponent);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
icon = getFirstMatch(page, isItemInFolder);
|
||||
if (icon != null) {
|
||||
return icon;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public View getHomescreenIconByItemId(final int id) {
|
||||
@@ -3002,21 +2965,38 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
|
||||
return value[0];
|
||||
}
|
||||
|
||||
private View getFirstMatch(CellLayout[] cellLayouts, final ItemOperator operator) {
|
||||
final View[] value = new View[1];
|
||||
/**
|
||||
* @param cellLayouts List of CellLayouts to scan, in order of preference.
|
||||
* @param operators List of operators, in order starting from best matching operator.
|
||||
* @return
|
||||
*/
|
||||
private View getFirstMatch(CellLayout[] cellLayouts, final ItemOperator... operators) {
|
||||
// This array is filled with the first match for each operator.
|
||||
final View[] matches = new View[operators.length];
|
||||
// For efficiency, the outer loop should be CellLayout.
|
||||
for (CellLayout cellLayout : cellLayouts) {
|
||||
mapOverCellLayout(MAP_NO_RECURSE, cellLayout, (info, v) -> {
|
||||
if (operator.evaluate(info, v)) {
|
||||
value[0] = v;
|
||||
return true;
|
||||
for (int i = 0; i < operators.length; ++i) {
|
||||
if (matches[i] == null && operators[i].evaluate(info, v)) {
|
||||
matches[i] = v;
|
||||
if (i == 0) {
|
||||
// We can return since this is the best match possible.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (value[0] != null) {
|
||||
if (matches[0] != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return value[0];
|
||||
for (View match : matches) {
|
||||
if (match != null) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void clearDropTargets() {
|
||||
|
||||
Reference in New Issue
Block a user