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

Commit 70fb53c2 authored by Mario Bertschler's avatar Mario Bertschler Committed by Android (Google) Code Review
Browse files

Merge "Using edge effect to trigger spring animation for all apps." into ub-launcher3-master

parents 73abd9d4 14a89262
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -31,7 +31,6 @@ 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.anim.SpringAnimationHandler;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@@ -142,11 +141,6 @@ public class EdgeSwipeController extends VerticalSwipeController implements
        }
    }

    @Override
    protected void initSprings() {
        mSpringHandlers = new SpringAnimationHandler[0];
    }

    @Override
    protected float getShiftRange() {
        return getShiftRange(mLauncher);
+0 −49
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
import static com.android.launcher3.anim.SpringAnimationHandler.Y_DIRECTION;
import static com.android.quickstep.TouchInteractionService.EDGE_NAV_BAR;

import android.animation.Animator;
@@ -27,7 +26,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.support.animation.SpringAnimation;
import android.util.Log;
import android.view.MotionEvent;

@@ -38,11 +36,9 @@ import com.android.launcher3.LauncherStateManager;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.SpringAnimationHandler;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@@ -52,8 +48,6 @@ import com.android.launcher3.util.FloatRange;
import com.android.launcher3.util.TouchController;
import com.android.quickstep.TouchInteractionService;

import java.util.ArrayList;

/**
 * Handles vertical touch gesture on the DragLayer
 */
@@ -112,8 +106,6 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter
    // Ratio of transition process [0, 1] to drag displacement (px)
    private float mProgressMultiplier;

    private SpringAnimationHandler[] mSpringHandlers;

    public TwoStepSwipeController(Launcher l) {
        mLauncher = l;
        mDetector = new SwipeDetector(l, this, SwipeDetector.VERTICAL);
@@ -156,29 +148,6 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter
        }
    }

    private void initSprings() {
        AllAppsContainerView appsView = mLauncher.getAppsView();

        SpringAnimationHandler handler = appsView.getSpringAnimationHandler();
        if (handler == null) {
            mSpringHandlers = new SpringAnimationHandler[0];
            return;
        }

        ArrayList<SpringAnimationHandler> handlers = new ArrayList<>();
        handlers.add(handler);

        SpringAnimation searchSpring = appsView.getSearchUiManager().getSpringForFling();
        if (searchSpring != null) {
            SpringAnimationHandler searchHandler =
                    new SpringAnimationHandler(Y_DIRECTION, handler.getFactory());
            searchHandler.add(searchSpring, true /* setDefaultValues */);
            handlers.add(searchHandler);
        }

        mSpringHandlers = handlers.toArray(new SpringAnimationHandler[handlers.size()]);
    }

    @Override
    public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
@@ -214,10 +183,6 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter

            mDetector.setDetectableScrollConditions(
                    directionsToDetectScroll, ignoreSlopWhenSettling);

            if (mSpringHandlers == null) {
                initSprings();
            }
        }

        if (mNoIntercept) {
@@ -230,9 +195,6 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter

    @Override
    public boolean onControllerTouchEvent(MotionEvent ev) {
        for (SpringAnimationHandler h : mSpringHandlers) {
            h.addMovement(ev);
        }
        return mDetector.onTouchEvent(ev);
    }

@@ -283,10 +245,6 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter
            mDragPauseDetector.clearDisabledFlags(FLAG_OVERVIEW_DISABLED_FLING);
            updatePauseDetectorRangeFlag();
        }

        for (SpringAnimationHandler h : mSpringHandlers) {
            h.skipToEnd();
        }
    }

    private float getShiftRange() {
@@ -329,13 +287,6 @@ public class TwoStepSwipeController extends AnimatorListenerAdapter
            targetState = (progress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
        }

        if (fling && targetState == ALL_APPS) {
            for (SpringAnimationHandler h : mSpringHandlers) {
                // The icons are moving upwards, so we go to 0 from 1. (y-axis 1 is below 0.)
                h.animateToFinalPosition(0 /* pos */, 1 /* startValue */);
            }
        }

        float endProgress;

        if (mDragPauseDetector.isTriggered() && targetState == NORMAL) {
+1 −2
Original line number Diff line number Diff line
@@ -22,5 +22,4 @@
    android:layout_below="@id/search_container_all_apps"
    android:clipToPadding="false"
    android:descendantFocusability="afterDescendants"
    android:focusable="true"
    android:overScrollMode="never" />
    android:focusable="true" />
+7 −12
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.android.launcher3.AppInfo;
import com.android.launcher3.DeviceProfile;
@@ -50,7 +49,6 @@ import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.anim.SpringAnimationHandler;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragOptions;
@@ -61,11 +59,12 @@ import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.BottomUserEducationView;
import com.android.launcher3.views.RecyclerViewFastScroller;
import com.android.launcher3.views.SpringRelativeLayout;

/**
 * The all apps view container.
 */
public class AllAppsContainerView extends RelativeLayout implements DragSource,
public class AllAppsContainerView extends SpringRelativeLayout implements DragSource,
        OnLongClickListener, Insettable, OnDeviceProfileChangeListener {

    private final Launcher mLauncher;
@@ -119,6 +118,10 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
        // Attach a scrim to be drawn behind all-apps and hotseat
        new ColorScrim(this, Themes.getAttrColor(context, R.attr.allAppsScrimColor), DEACCEL_2)
                .attach();

        addSpringView(R.id.all_apps_header);
        addSpringView(R.id.apps_list_view);
        addSpringView(R.id.all_apps_tabs_view_pager);
    }

    public AllAppsStore getAppsStore() {
@@ -324,10 +327,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
        }
    }

    public SpringAnimationHandler getSpringAnimationHandler() {
        return mUsingTabs ? null : mAH[AdapterHolder.MAIN].animationHandler;
    }

    private void rebindAdapters(boolean showTabs) {
        rebindAdapters(showTabs, false /* force */);
    }
@@ -470,7 +469,6 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,

        public final AllAppsGridAdapter adapter;
        final LinearLayoutManager layoutManager;
        final SpringAnimationHandler animationHandler;
        final AlphabeticalAppsList appsList;
        final Rect padding = new Rect();
        AllAppsRecyclerView recyclerView;
@@ -481,22 +479,19 @@ public class AllAppsContainerView extends RelativeLayout implements DragSource,
            adapter = new AllAppsGridAdapter(mLauncher, appsList, mLauncher,
                    AllAppsContainerView.this, true);
            appsList.setAdapter(adapter);
            animationHandler = adapter.getSpringAnimationHandler();
            layoutManager = adapter.getLayoutManager();
        }

        void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
            appsList.updateItemFilter(matcher);
            recyclerView = (AllAppsRecyclerView) rv;
            recyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
            recyclerView.setApps(appsList, mUsingTabs);
            recyclerView.setLayoutManager(layoutManager);
            recyclerView.setAdapter(adapter);
            recyclerView.setHasFixedSize(true);
            // No animations will occur when changes occur to the items in this RecyclerView.
            recyclerView.setItemAnimator(null);
            if (FeatureFlags.LAUNCHER3_PHYSICS && animationHandler != null) {
                recyclerView.setSpringAnimationHandler(animationHandler);
            }
            FocusedItemDecorator focusedItemDecorator = new FocusedItemDecorator(recyclerView);
            recyclerView.addItemDecoration(focusedItemDecorator);
            adapter.setIconFocusListener(focusedItemDecorator.getFocusListener());
+0 −134
Original line number Diff line number Diff line
@@ -18,8 +18,6 @@ package com.android.launcher3.allapps;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.support.animation.DynamicAnimation;
import android.support.animation.SpringAnimation;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
@@ -38,11 +36,8 @@ import com.android.launcher3.AppInfo;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.AlphabeticalAppsList.AdapterItem;
import com.android.launcher3.anim.SpringAnimationHandler;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.PackageManagerHelper;

import java.util.List;
@@ -71,7 +66,6 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
    // 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_HAS_SPRINGS = VIEW_TYPE_MASK_ICON;


    public interface BindViewCallback {
@@ -195,8 +189,6 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
    // The intent to send off to the market app, updated each time the search query changes.
    private Intent mMarketSearchIntent;

    private final SpringAnimationHandler<ViewHolder> mSpringAnimationHandler;

    public AllAppsGridAdapter(Launcher launcher, AlphabeticalAppsList apps, View.OnClickListener
            iconClickListener, View.OnLongClickListener iconLongClickListener, boolean springAnim) {
        Resources res = launcher.getResources();
@@ -209,21 +201,11 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
        mLayoutInflater = LayoutInflater.from(launcher);
        mIconClickListener = iconClickListener;
        mIconLongClickListener = iconLongClickListener;
        if (FeatureFlags.LAUNCHER3_PHYSICS && springAnim) {
            mSpringAnimationHandler = new SpringAnimationHandler<>(
                    SpringAnimationHandler.Y_DIRECTION, new AllAppsSpringAnimationFactory());
        } else {
            mSpringAnimationHandler = null;
        }

        mAppsPerRow = mLauncher.getDeviceProfile().inv.numColumns;
        mGridLayoutMgr.setSpanCount(mAppsPerRow);
    }

    public SpringAnimationHandler getSpringAnimationHandler() {
        return mSpringAnimationHandler;
    }

    public static boolean isDividerViewType(int viewType) {
        return isViewType(viewType, VIEW_TYPE_MASK_DIVIDER);
    }
@@ -343,22 +325,6 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
        }
    }

    @Override
    public void onViewAttachedToWindow(ViewHolder holder) {
        int type = holder.getItemViewType();
        if (mSpringAnimationHandler != null && isViewType(type, VIEW_TYPE_MASK_HAS_SPRINGS)) {
            mSpringAnimationHandler.add(holder.itemView, holder);
        }
    }

    @Override
    public void onViewDetachedFromWindow(ViewHolder holder) {
        int type = holder.getItemViewType();
        if (mSpringAnimationHandler != null && isViewType(type, VIEW_TYPE_MASK_HAS_SPRINGS)) {
            mSpringAnimationHandler.remove(holder.itemView);
        }
    }

    @Override
    public boolean onFailedToRecycleView(ViewHolder holder) {
        // Always recycle and we will reset the view when it is bound
@@ -376,104 +342,4 @@ public class AllAppsGridAdapter extends RecyclerView.Adapter<AllAppsGridAdapter.
        return item.viewType;
    }

    /**
     * Helper class to set the SpringAnimation values for an item in the adapter.
     */
    private class AllAppsSpringAnimationFactory
            implements SpringAnimationHandler.AnimationFactory<ViewHolder> {
        private static final float DEFAULT_MAX_VALUE_PX = 100;
        private static final float DEFAULT_MIN_VALUE_PX = -DEFAULT_MAX_VALUE_PX;

        // Damping ratio range is [0, 1]
        private static final float SPRING_DAMPING_RATIO = 0.55f;

        // Stiffness is a non-negative number.
        private static final float MIN_SPRING_STIFFNESS = 580f;
        private static final float MAX_SPRING_STIFFNESS = 900f;

        // The amount by which each adjacent rows' stiffness will differ.
        private static final float ROW_STIFFNESS_COEFFICIENT = 50f;

        // The percentage by which we multiply each row to create the row factor.
        private static final float ROW_PERCENTAGE = 0.3f;

        @Override
        public SpringAnimation initialize(ViewHolder vh) {
            return SpringAnimationHandler.forView(vh.itemView, DynamicAnimation.TRANSLATION_Y, 0);
        }

        /**
         * @param spring A new or recycled SpringAnimation.
         * @param vh The ViewHolder that {@param spring} is related to.
         */
        @Override
        public void update(SpringAnimation spring, ViewHolder vh) {
            int appPosition = vh.getAdapterPosition();
            int col = appPosition % mAppsPerRow;
            int row = appPosition / mAppsPerRow;

            int numTotalRows = mApps.getNumAppRows() - 1; // zero-based count
            if (row > (numTotalRows / 2)) {
                // Mirror the rows so that the top row acts the same as the bottom row.
                row = Math.abs(numTotalRows - row);
            }

            calculateSpringValues(spring, row, col);
        }

        @Override
        public void setDefaultValues(SpringAnimation spring) {
            calculateSpringValues(spring, 0, mAppsPerRow / 2);
        }

        /**
         * We manipulate the stiffness, min, and max values based on the items distance to the
         * first row and the items distance to the center column to create the ^-shaped motion
         * effect.
         */
        private void calculateSpringValues(SpringAnimation spring, int row, int col) {
            float rowFactor = (1 + row) * ROW_PERCENTAGE;
            float colFactor = getColumnFactor(col, mAppsPerRow);

            float minValue = DEFAULT_MIN_VALUE_PX * (rowFactor + colFactor);
            float maxValue = DEFAULT_MAX_VALUE_PX * (rowFactor + colFactor);

            float stiffness = Utilities.boundToRange(
                    MAX_SPRING_STIFFNESS - (row * ROW_STIFFNESS_COEFFICIENT),
                    MIN_SPRING_STIFFNESS,
                    MAX_SPRING_STIFFNESS);

            spring.setMinValue(minValue)
                    .setMaxValue(maxValue)
                    .getSpring()
                    .setStiffness(stiffness)
                    .setDampingRatio(SPRING_DAMPING_RATIO);
        }

        /**
         * Increase the column factor as the distance increases between the column and the center
         * column(s).
         */
        private float getColumnFactor(int col, int numCols) {
            float centerColumn = numCols / 2;
            int distanceToCenter = (int) Math.abs(col - centerColumn);

            boolean evenNumberOfColumns = numCols % 2 == 0;
            if (evenNumberOfColumns && col < centerColumn) {
                distanceToCenter -= 1;
            }

            float factor = 0;
            while (distanceToCenter > 0) {
                if (distanceToCenter == 1) {
                    factor += 0.2f;
                } else {
                    factor += 0.1f;
                }
                --distanceToCenter;
            }

            return factor;
        }
    }
}
Loading