Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5ac7eb1e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Updates to app to icon animation, and turns on...

Merge "Updates to app to icon animation, and turns on ADAPTIVE_ICON_WINDOW_ANIM flag." into ub-launcher3-master
parents f520c6ca 4334874f
Loading
Loading
Loading
Loading
+5 −4
Original line number Original line Diff line number Diff line
@@ -29,11 +29,11 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ObjectAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region;
import android.os.UserHandle;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;
import android.view.animation.Interpolator;
import android.view.animation.Interpolator;
@@ -102,9 +102,10 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
        final RecentsView recentsView = activity.getOverviewPanel();
        final RecentsView recentsView = activity.getOverviewPanel();
        final TaskView runningTaskView = recentsView.getRunningTaskView();
        final TaskView runningTaskView = recentsView.getRunningTaskView();
        final View workspaceView;
        final View workspaceView;
        if (runningTaskView != null) {
        if (runningTaskView != null && runningTaskView.getTask().key.getComponent() != null) {
            ComponentName component = runningTaskView.getTask().key.sourceComponent;
            workspaceView = activity.getWorkspace().getFirstMatchForAppClose(
            workspaceView = activity.getWorkspace().getFirstMatchForAppClose(component);
                    runningTaskView.getTask().key.getComponent().getPackageName(),
                    UserHandle.of(runningTaskView.getTask().key.userId));
        } else {
        } else {
            workspaceView = null;
            workspaceView = null;
        }
        }
+54 −74
Original line number Original line Diff line number Diff line
@@ -19,9 +19,13 @@ package com.android.launcher3;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
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_EXIT_DELAY;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_TRANSITION_MS;
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.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
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 static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_OVERLAY;


import android.animation.Animator;
import android.animation.Animator;
@@ -34,7 +38,6 @@ import android.annotation.SuppressLint;
import android.app.WallpaperManager;
import android.app.WallpaperManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap;
@@ -47,6 +50,7 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Message;
import android.os.Parcelable;
import android.os.Parcelable;
import android.os.UserHandle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseArray;
@@ -99,8 +103,6 @@ import com.android.launcher3.widget.PendingAppWidgetHostView;


import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Predicate;


/**
/**
@@ -1612,7 +1614,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>


        boolean aboveShortcut = (dropOverView.getTag() instanceof ShortcutInfo);
        boolean aboveShortcut = (dropOverView.getTag() instanceof ShortcutInfo);
        boolean willBecomeShortcut =
        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_SHORTCUT ||
                        info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);
                        info.itemType == LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT);


@@ -2520,7 +2522,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
            View view;
            View view;


            switch (info.itemType) {
            switch (info.itemType) {
            case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
            case ITEM_TYPE_APPLICATION:
            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
            case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
            case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                if (info.container == NO_ID && info instanceof AppInfo) {
                if (info.container == NO_ID && info instanceof AppInfo) {
@@ -2895,52 +2897,30 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
        return layouts;
        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
     * Similar to {@link #getFirstMatch} but optimized to finding a suitable view for the app close
     * animation.
     * 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 int curPage = getCurrentPage();
        final CellLayout currentPage = (CellLayout) getPageAt(curPage);
        final CellLayout currentPage = (CellLayout) getPageAt(curPage);
        final Workspace.ItemOperator isItemComponent = (info, view) ->
        final Workspace.ItemOperator packageAndUser = (ItemInfo info, View view) -> info != null
                info != null && Objects.equals(info.getTargetComponent(), component);
                && info.getTargetComponent() != null
        final Workspace.ItemOperator isItemInFolder = (info, view) -> {
                && 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) {
            if (info instanceof FolderInfo) {
                FolderInfo folderInfo = (FolderInfo) info;
                FolderInfo folderInfo = (FolderInfo) info;
                for (ShortcutInfo shortcutInfo : folderInfo.contents) {
                for (ShortcutInfo shortcutInfo : folderInfo.contents) {
                    if (Objects.equals(shortcutInfo.getTargetComponent(), component)) {
                    if (packageAndUser.evaluate(shortcutInfo, view)) {
                        return true;
                        return true;
                    }
                    }
                }
                }
@@ -2948,33 +2928,16 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
            return false;
            return false;
        };
        };


        CellLayout[] hotseatAndCurrentPage = new CellLayout[] { getHotseat(), currentPage };
        // Order: App icons, shortcuts, app/shortcut in folder. Items in hotseat get returned first.
        // First we look if the app itself is in the hotseat or on the current workspace page.
        if (ADAPTIVE_ICON_WINDOW_ANIM.get()) {
        View icon = getFirstMatch(hotseatAndCurrentPage, isItemComponent);
            return getFirstMatch(new CellLayout[] { getHotseat(), currentPage },
        if (icon != null) {
                    packageAndUserAndApp, packageAndUserAndShortcut, packageAndUserInFolder);
            return icon;
        } else {
        }
            // Do not use Folder as a criteria, since it'll cause a crash when trying to draw
        // Then we look if the app is in a folder on the hotseat or current workspace page.
            // FolderAdaptiveIcon as the background.
        icon = getFirstMatch(hotseatAndCurrentPage, isItemInFolder);
            return getFirstMatch(new CellLayout[] { getHotseat(), currentPage },
        if (icon != null) {
                    packageAndUserAndApp, packageAndUserAndShortcut);
            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) {
    public View getHomescreenIconByItemId(final int id) {
@@ -3002,21 +2965,38 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
        return value[0];
        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) {
        for (CellLayout cellLayout : cellLayouts) {
            mapOverCellLayout(MAP_NO_RECURSE, cellLayout, (info, v) -> {
            mapOverCellLayout(MAP_NO_RECURSE, cellLayout, (info, v) -> {
                if (operator.evaluate(info, v)) {
                for (int i = 0; i < operators.length; ++i) {
                    value[0] = v;
                    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 true;
                        }
                        }
                    }
                }
                return false;
                return false;
            });
            });
            if (value[0] != null) {
            if (matches[0] != null) {
                break;
                break;
            }
            }
        }
        }
        return value[0];
        for (View match : matches) {
            if (match != null) {
                return match;
            }
        }
        return null;
    }
    }


    void clearDropTargets() {
    void clearDropTargets() {
+1 −1
Original line number Original line Diff line number Diff line
@@ -102,7 +102,7 @@ abstract class BaseFlags {
            false, "Enable springs for quickstep animations");
            false, "Enable springs for quickstep animations");


    public static final TogglableFlag ADAPTIVE_ICON_WINDOW_ANIM = new TogglableFlag(
    public static final TogglableFlag ADAPTIVE_ICON_WINDOW_ANIM = new TogglableFlag(
            "ADAPTIVE_ICON_WINDOW_ANIM", false,
            "ADAPTIVE_ICON_WINDOW_ANIM", true,
            "Use adaptive icons for window animations.");
            "Use adaptive icons for window animations.");


    public static final TogglableFlag ENABLE_QUICKSTEP_LIVE_TILE = new TogglableFlag(
    public static final TogglableFlag ENABLE_QUICKSTEP_LIVE_TILE = new TogglableFlag(
+19 −7
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import android.view.ViewOutlineProvider;


import com.android.launcher3.BubbleTextView;
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.Launcher;
@@ -81,7 +82,7 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,


    private final Rect mFinalDrawableBounds = new Rect();
    private final Rect mFinalDrawableBounds = new Rect();
    private final Rect mBgDrawableBounds = new Rect();
    private final Rect mBgDrawableBounds = new Rect();
    private final float mBgDrawableStartScale = 5f; // Magic number that can be tuned later.
    private float mBgDrawableStartScale = 1f;


    private FloatingIconView(Context context) {
    private FloatingIconView(Context context) {
        super(context);
        super(context);
@@ -188,12 +189,19 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,
    private void getIcon(Launcher launcher, View v, ItemInfo info, boolean useDrawableAsIs,
    private void getIcon(Launcher launcher, View v, ItemInfo info, boolean useDrawableAsIs,
            float aspectRatio) {
            float aspectRatio) {
        final LayoutParams lp = (LayoutParams) getLayoutParams();
        final LayoutParams lp = (LayoutParams) getLayoutParams();
        mDrawable = Utilities.getFullDrawable(launcher, info, lp.width, lp.height, useDrawableAsIs,
                new Object[1]);


        if (ADAPTIVE_ICON_WINDOW_ANIM.get() && !useDrawableAsIs
        boolean supportsAdaptiveIcons = ADAPTIVE_ICON_WINDOW_ANIM.get() && !useDrawableAsIs
                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
                && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
                && mDrawable instanceof AdaptiveIconDrawable) {
        if (!supportsAdaptiveIcons && v instanceof BubbleTextView) {
            // Similar to DragView, we simply use the BubbleTextView icon here.
            mDrawable = ((BubbleTextView) v).getIcon();
        }
        if (mDrawable == null) {
            mDrawable = Utilities.getFullDrawable(launcher, info, lp.width, lp.height,
                    useDrawableAsIs, new Object[1]);
        }

        if (supportsAdaptiveIcons && mDrawable instanceof AdaptiveIconDrawable) {
            mIsAdaptiveIcon = true;
            mIsAdaptiveIcon = true;


            AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) mDrawable;
            AdaptiveIconDrawable adaptiveIcon = (AdaptiveIconDrawable) mDrawable;
@@ -227,8 +235,9 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,
                lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
                lp.height = (int) Math.max(lp.height, lp.width * aspectRatio);
                layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
                layout(lp.leftMargin, lp.topMargin, lp.leftMargin + lp.width, lp.topMargin
                        + lp.height);
                        + lp.height);
                setBackgroundDrawableBounds(mBgDrawableStartScale);
            }
            }
            mBgDrawableStartScale = (float) lp.height / mOriginalHeight;
            setBackgroundDrawableBounds(mBgDrawableStartScale);


            // Set up outline
            // Set up outline
            mOutline.set(0, 0, lp.width, lp.height);
            mOutline.set(0, 0, lp.width, lp.height);
@@ -252,6 +261,9 @@ public class FloatingIconView extends View implements Animator.AnimatorListener,
    private void setBackgroundDrawableBounds(float scale) {
    private void setBackgroundDrawableBounds(float scale) {
        mBgDrawableBounds.set(mFinalDrawableBounds);
        mBgDrawableBounds.set(mFinalDrawableBounds);
        Utilities.scaleRectAboutCenter(mBgDrawableBounds, scale);
        Utilities.scaleRectAboutCenter(mBgDrawableBounds, scale);
        // Since the drawable is at the top of the view, we need to offset to keep it centered.
        mBgDrawableBounds.offsetTo(mBgDrawableBounds.left,
                (int) (mFinalDrawableBounds.top * scale));
        mBackground.setBounds(mBgDrawableBounds);
        mBackground.setBounds(mBgDrawableBounds);
    }
    }