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

Commit 553a2c87 authored by Brandon Dayauon's avatar Brandon Dayauon Committed by Android (Google) Code Review
Browse files

Merge "Apply the expand animation on Private Space" into main

parents cc5db618 98bf9f75
Loading
Loading
Loading
Loading
+35 −1
Original line number Diff line number Diff line
@@ -15,6 +15,10 @@
 */
package com.android.launcher3.allapps;

import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_LEFT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_RIGHT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_NOTHING;

import android.content.Context;

import androidx.annotation.Nullable;
@@ -318,6 +322,10 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
                case PrivateProfileManager.STATE_ENABLED:
                    // Add PS Apps only in Enabled State.
                    addAppsWithSections(mPrivateApps, position);
                    if (mActivityContext.getAppsView() != null) {
                        mActivityContext.getAppsView().getActiveRecyclerView()
                                .scrollToBottomWithMotion();
                    }
                    break;
            }
        }
@@ -325,8 +333,34 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement

    private void addAppsWithSections(List<AppInfo> appList, int startPosition) {
        String lastSectionName = null;
        boolean hasPrivateApps = false;
        if (mPrivateProviderManager != null) {
            hasPrivateApps = appList.stream().
                    allMatch(mPrivateProviderManager.getItemInfoMatcher());
        }
        int privateAppCount = 0;
        int numberOfColumns = mActivityContext.getDeviceProfile().numShownAllAppsColumns;
        int numberOfAppRows = (int) Math.ceil((double) appList.size() / numberOfColumns);
        for (AppInfo info : appList) {
            // Apply decorator to private apps.
            if (hasPrivateApps) {
                int roundRegion = ROUND_NOTHING;
                if ((privateAppCount / numberOfColumns) == numberOfAppRows - 1) {
                    if ((privateAppCount % numberOfColumns) == 0) {
                        // App is the first column
                        roundRegion = ROUND_BOTTOM_LEFT;
                    } else if ((privateAppCount % numberOfColumns) == numberOfColumns-1) {
                        roundRegion = ROUND_BOTTOM_RIGHT;
                    }
                }
                mAdapterItems.add(AdapterItem.asAppWithDecorationInfo(info,
                        new SectionDecorationInfo(mActivityContext.getApplicationContext(),
                                roundRegion,
                                true /* decorateTogether */)));
                privateAppCount += 1;
            } else {
                mAdapterItems.add(AdapterItem.asApp(info));
            }

            String sectionName = info.sectionName;
            // Create a new section if the section names do not match
+22 −0
Original line number Diff line number Diff line
@@ -15,6 +15,12 @@
 */
package com.android.launcher3.allapps;

import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_LEFT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_BOTTOM_RIGHT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_TOP_LEFT;
import static com.android.launcher3.allapps.SectionDecorationInfo.ROUND_TOP_RIGHT;
import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
@@ -108,6 +114,13 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
            return item;
        }

        public static AdapterItem asAppWithDecorationInfo(AppInfo appInfo,
                SectionDecorationInfo decorationInfo) {
            AdapterItem item = asApp(appInfo);
            item.decorationInfo = decorationInfo;
            return item;
        }

        protected boolean isCountedForAccessibility() {
            return viewType == VIEW_TYPE_ICON;
        }
@@ -259,6 +272,15 @@ public abstract class BaseAllAppsAdapter<T extends Context & ActivityContext> ex
                assert mPrivateSpaceHeaderViewController != null;
                assert psHeaderLayout != null;
                mPrivateSpaceHeaderViewController.addPrivateSpaceHeaderViewElements(psHeaderLayout);
                AdapterItem adapterItem = mApps.getAdapterItems().get(position);
                int roundRegions = ROUND_TOP_LEFT | ROUND_TOP_RIGHT;
                if (mPrivateSpaceHeaderViewController.getPrivateProfileManager().getCurrentState()
                        == STATE_DISABLED) {
                    roundRegions |= (ROUND_BOTTOM_LEFT | ROUND_BOTTOM_RIGHT);
                }
                adapterItem.decorationInfo =
                        new SectionDecorationInfo(mActivityContext, roundRegions,
                                false /* decorateTogether */);
                break;
            case VIEW_TYPE_ALL_APPS_DIVIDER:
            case VIEW_TYPE_WORK_DISABLED_CARD:
+24 −66
Original line number Diff line number Diff line
@@ -16,97 +16,55 @@

package com.android.launcher3.allapps;

import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_ICON;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_PRIVATE_SPACE_HEADER;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.View;

import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;

import com.android.launcher3.R;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.views.ActivityContext;
import java.util.HashMap;

/**
 * Decorator which changes the background color for Private Space Icon Rows in AllAppsContainer.
 */
public class PrivateAppsSectionDecorator extends RecyclerView.ItemDecoration {

    private final Path mTmpPath = new Path();
    private final RectF mTmpRect = new RectF();
    private final Context mContext;
    private static final String PRIVATE_APP_SECTION = "private_apps";
    private final AlphabeticalAppsList<?> mAppsList;
    private final UserCache mUserCache;
    private final Paint mPaint;
    private final int mCornerRadius;

    public PrivateAppsSectionDecorator(Context context, AlphabeticalAppsList<?> appsList) {
        mContext = context;
    public PrivateAppsSectionDecorator(AlphabeticalAppsList<?> appsList) {
        mAppsList = appsList;
        mUserCache = UserCache.getInstance(context);
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(ContextCompat.getColor(context,
                R.color.material_color_surface_container_high));
        mCornerRadius = context.getResources().getDimensionPixelSize(
                R.dimen.ps_container_corner_radius);
    }

    /** Decorates Private Space Header and Icon Rows to give the shape of a container. */
    @Override
    public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
        mTmpPath.reset();
        mTmpRect.setEmpty();
        int numCol = ActivityContext.lookupContext(mContext).getDeviceProfile()
                .numShownAllAppsColumns;
        HashMap<String, SectionDecorationHandler.UnionDecorationHandler> deferredDecorations =
                new HashMap<>();
        for (int i = 0; i < parent.getChildCount(); i++) {
            View view = parent.getChildAt(i);
            int position = parent.getChildAdapterPosition(view);
            BaseAllAppsAdapter.AdapterItem adapterItem = mAppsList.getAdapterItems().get(position);
            // Rectangle that covers the bottom half of the PS Header View when Space is unlocked.
            if (adapterItem.viewType == VIEW_TYPE_PRIVATE_SPACE_HEADER) {
                // We flatten the bottom corners of the rectangle, so that it merges with
                // the private space app row decorator.
                mTmpRect.set(
                        view.getLeft(),
                        view.getTop() + (float) (view.getBottom() - view.getTop()) / 2,
                        view.getRight(),
                        view.getBottom());
                mTmpPath.addRect(mTmpRect, Path.Direction.CW);
                c.drawPath(mTmpPath, mPaint);
            } else if (adapterItem.viewType == VIEW_TYPE_ICON
                    && mUserCache.getUserInfo(adapterItem.itemInfo.user).isPrivate()
                    // No decoration for any private space app icon other than those at first row.
                    && adapterItem.rowAppIndex == 0) {
                c.drawPath(getPrivateAppRowPath(parent, view, position, numCol), mPaint);
            SectionDecorationInfo info = adapterItem.decorationInfo;
            if (info == null) {
                continue;
            }
            SectionDecorationHandler decorationHandler = info.getDecorationHandler();
            if (info.shouldDecorateItemsTogether()) {
                SectionDecorationHandler.UnionDecorationHandler unionHandler =
                        deferredDecorations.getOrDefault(
                                PRIVATE_APP_SECTION,
                                new SectionDecorationHandler.UnionDecorationHandler(
                                        decorationHandler, parent.getPaddingLeft(),
                                        parent.getPaddingRight()));
                unionHandler.addChild(decorationHandler, view, true /* applyBackground */);
                deferredDecorations.put(PRIVATE_APP_SECTION, unionHandler);
            } else {
                decorationHandler.onFocusDraw(c, view);
            }
        }

    /** Returns the path to be decorated for Private Space App Row */
    private Path getPrivateAppRowPath(RecyclerView parent, View iconView, int adapterPosition,
            int numCol) {
        // We always decorate the entire app row here.
        // As the iconView just represents the first icon of the row, we get the right margin of
        // our decorator using the parent view.
        mTmpRect.set(iconView.getLeft(),
                iconView.getTop(),
                parent.getRight() - parent.getPaddingRight(),
                iconView.getBottom());
        // Decorates last app row with rounded bottom corners.
        if (adapterPosition + numCol >= mAppsList.getAdapterItems().size()) {
            float[] mCornersBot = new float[]{0, 0, 0, 0, mCornerRadius, mCornerRadius,
                    mCornerRadius, mCornerRadius};
            mTmpPath.addRoundRect(mTmpRect, mCornersBot, Path.Direction.CW);
        } else {
            // Decorate other rows as a plain rectangle
            mTmpPath.addRect(mTmpRect, Path.Direction.CW);
        for (SectionDecorationHandler.UnionDecorationHandler decorationHandler
                : deferredDecorations.values()) {
            decorationHandler.onGroupDecorate(c);
        }
        return mTmpPath;
    }
}
+9 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import android.os.UserManager;

import androidx.annotation.VisibleForTesting;

import com.android.launcher3.Flags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.util.Preconditions;
@@ -47,6 +48,7 @@ public class PrivateProfileManager extends UserProfileManager {
    private static final String SAFETY_CENTER_INTENT = Intent.ACTION_SAFETY_CENTER;
    private static final String PS_SETTINGS_FRAGMENT_KEY = ":settings:fragment_args_key";
    private static final String PS_SETTINGS_FRAGMENT_VALUE = "AndroidPrivateSpace_personal";
    private static final int ANIMATION_DURATION = 2000;
    private final ActivityAllAppsContainerView<?> mAllApps;
    private final Predicate<UserHandle> mPrivateProfileMatcher;
    private PrivateAppsSectionDecorator mPrivateAppsSectionDecorator;
@@ -125,7 +127,6 @@ public class PrivateProfileManager extends UserProfileManager {
            // Create a new decorator instance if not already available.
            if (mPrivateAppsSectionDecorator == null) {
                mPrivateAppsSectionDecorator = new PrivateAppsSectionDecorator(
                        mAllApps.mActivityContext,
                        mainAdapterHolder.mAppsList);
            }
            for (int i = 0; i < mainAdapterHolder.mRecyclerView.getItemDecorationCount(); i++) {
@@ -137,6 +138,13 @@ public class PrivateProfileManager extends UserProfileManager {
            }
            // Add Private Space Decorator to the Recycler view.
            mainAdapterHolder.mRecyclerView.addItemDecoration(mPrivateAppsSectionDecorator);
            if (Flags.privateSpaceAnimation() && mAllApps.getActiveRecyclerView()
                    == mainAdapterHolder.mRecyclerView) {
                RecyclerViewAnimationController recyclerViewAnimationController =
                        new RecyclerViewAnimationController(mAllApps);
                recyclerViewAnimationController.animateToState(true /* expand */,
                        ANIMATION_DURATION, () -> {});
            }
        } else {
            // Remove Private Space Decorator from the Recycler view.
            if (mPrivateAppsSectionDecorator != null) {
+4 −0
Original line number Diff line number Diff line
@@ -105,4 +105,8 @@ public class PrivateSpaceHeaderViewController {
            transitionImage.setVisibility(View.GONE);
        }
    }

    PrivateProfileManager getPrivateProfileManager() {
        return mPrivateProfileManager;
    }
}