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

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

Merge "Predictive swipe: show extra app icons at bottom of All Apps's...

Merge "Predictive swipe: show extra app icons at bottom of All Apps's RecyclerViews" into tm-qpr-dev
parents a329718d 3774824c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -37,4 +37,6 @@
    <item type="id" name="quick_settings_button" />
    <item type="id" name="notifications_button" />
    <item type="id" name="cache_entry_tag_id" />

    <item type="id" name="saved_clip_children_tag_id" />
</resources>
+14 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;

import androidx.annotation.Px;
import androidx.core.view.accessibility.AccessibilityEventCompat;
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
import androidx.core.view.accessibility.AccessibilityRecordCompat;
@@ -143,6 +144,19 @@ public class AllAppsGridAdapter<T extends Context & ActivityContext> extends
                    cic.isSelected()));
        }

        /**
         * We need to extend all apps' RecyclerView's bottom by 5% of view height to ensure extra
         * roll(s) of app icons is rendered at the bottom, so that they can fill the bottom gap
         * created during predictive back's scale animation from all apps to home.
         */
        @Override
        protected void calculateExtraLayoutSpace(RecyclerView.State state, int[] extraLayoutSpace) {
            super.calculateExtraLayoutSpace(state, extraLayoutSpace);
            @Px int extraSpacePx = (int) (getHeight()
                    * (1 - AllAppsTransitionController.SWIPE_ALL_APPS_TO_HOME_MIN_SCALE) / 2);
            extraLayoutSpace[1] = Math.max(extraLayoutSpace[1], extraSpacePx);
        }

        /**
         * Returns the number of rows before {@param adapterPosition}, including this position
         * which should not be counted towards the collection info.
+92 −3
Original line number Diff line number Diff line
@@ -32,14 +32,18 @@ import android.animation.ObjectAnimator;
import android.util.FloatProperty;
import android.view.HapticFeedbackConstants;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.Interpolator;

import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;

import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.Interpolators;
@@ -66,7 +70,7 @@ public class AllAppsTransitionController
        implements StateHandler<LauncherState>, OnDeviceProfileChangeListener {
    // This constant should match the second derivative of the animator interpolator.
    public static final float INTERP_COEFF = 1.7f;
    private static final float SWIPE_ALL_APPS_TO_HOME_MIN_SCALE = 0.9f;
    public static final float SWIPE_ALL_APPS_TO_HOME_MIN_SCALE = 0.9f;
    private static final int REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS = 200;

    public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
@@ -168,6 +172,8 @@ public class AllAppsTransitionController

    private boolean mIsTablet;

    private boolean mHasScaleEffect;

    public AllAppsTransitionController(Launcher l) {
        mLauncher = l;
        DeviceProfile dp = mLauncher.getDeviceProfile();
@@ -276,8 +282,18 @@ public class AllAppsTransitionController
            rv.getScrollbar().setVisibility(scaleProgress < 1f ? View.INVISIBLE : View.VISIBLE);
        }

        // TODO(b/264906511): We need to disable view clipping on all apps' parent views so
        //  that the extra roll of app icons are displayed.
        // Disable view clipping from all apps' RecyclerView up to all apps view during scale
        // animation, and vice versa. The goal is to display extra roll(s) app icons (rendered in
        // {@link AppsGridLayoutManager#calculateExtraLayoutSpace}) during scale animation.
        boolean hasScaleEffect = scaleProgress < 1f;
        if (hasScaleEffect != mHasScaleEffect) {
            mHasScaleEffect = hasScaleEffect;
            if (mHasScaleEffect) {
                setClipChildrenOnViewTree(rv, mLauncher.getAppsView(), false);
            } else {
                restoreClipChildrenOnViewTree(rv, mLauncher.getAppsView());
            }
        }
    }

    private void animateAllAppsToNoScale() {
@@ -380,6 +396,79 @@ public class AllAppsTransitionController
        mShouldControlKeyboard = !mLauncher.getSearchConfig().isKeyboardSyncEnabled();
    }

    /**
     * Recursively call {@link ViewGroup#setClipChildren(boolean)} from {@link View} to ts parent
     * (direct or indirect) inclusive. This method will also save the old clipChildren value on each
     * view with {@link View#setTag(int, Object)}, which can be restored in
     * {@link #restoreClipChildrenOnViewTree(View, ViewParent)}.
     *
     * Note that if parent is null or not a parent of the view, this method will be applied all the
     * way to root view.
     *
     * @param v child view
     * @param parent direct or indirect parent of child view
     * @param clipChildren whether we should clip children
     */
    private static void setClipChildrenOnViewTree(
            @Nullable View v,
            @Nullable ViewParent parent,
            boolean clipChildren) {
        if (v == null) {
            return;
        }

        if (v instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) v;
            boolean oldClipChildren = viewGroup.getClipChildren();
            if (oldClipChildren != clipChildren) {
                v.setTag(R.id.saved_clip_children_tag_id, oldClipChildren);
                viewGroup.setClipChildren(clipChildren);
            }
        }

        if (v == parent) {
            return;
        }

        if (v.getParent() instanceof View) {
            setClipChildrenOnViewTree((View) v.getParent(), parent, clipChildren);
        }
    }

    /**
     * Recursively call {@link ViewGroup#setClipChildren(boolean)} to restore clip children value
     * set in {@link #setClipChildrenOnViewTree(View, ViewParent, boolean)} on view to its parent
     * (direct or indirect) inclusive.
     *
     * Note that if parent is null or not a parent of the view, this method will be applied all the
     * way to root view.
     *
     * @param v child view
     * @param parent direct or indirect parent of child view
     */
    private static void restoreClipChildrenOnViewTree(
            @Nullable View v, @Nullable ViewParent parent) {
        if (v == null) {
            return;
        }
        if (v instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) v;
            Object viewTag = viewGroup.getTag(R.id.saved_clip_children_tag_id);
            if (viewTag instanceof Boolean) {
                viewGroup.setClipChildren((boolean) viewTag);
                viewGroup.setTag(R.id.saved_clip_children_tag_id, null);
            }
        }

        if (v == parent) {
            return;
        }

        if (v.getParent() instanceof View) {
            restoreClipChildrenOnViewTree((View) v.getParent(), parent);
        }
    }

    /**
     * Updates the total scroll range but does not update the UI.
     */