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

Commit bc683e9d authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Separating various UI properties into state variables

> Using workspace scale and translation for all-apps
> Without quickstep, workspace has the parallex effect as before
> With quickstep, workspace scales down to match the recents card width
> Using a single animator for recents views in case of state transtion and
  controlled transition to prevent going into inconsistant state.

Change-Id: I1864de6892052ca771f4d0062e3d60c28840a72d
parent 92731d48
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -13,9 +13,10 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.launcher3.states;
package com.android.launcher3.uioverrides;

import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS;
import static com.android.launcher3.allapps.DiscoveryBounce.APPS_VIEW_SHOWN;

import android.view.View;

@@ -30,8 +31,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
 */
public class AllAppsState extends LauncherState {

    public static final String APPS_VIEW_SHOWN = "launcher.apps_view_shown";

    private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY;

    public AllAppsState(int id) {
@@ -57,4 +56,15 @@ public class AllAppsState extends LauncherState {
    public View getFinalFocus(Launcher launcher) {
        return launcher.getAppsView();
    }

    @Override
    public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
        // TODO: interpolate
        return LauncherState.OVERVIEW.getWorkspaceScaleAndTranslation(launcher);
    }

    @Override
    public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
        return (i) -> 0;
    }
}
+17 −3
Original line number Diff line number Diff line
@@ -17,10 +17,12 @@ package com.android.launcher3.uioverrides;

import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;

import android.graphics.Rect;
import android.view.View;

import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Workspace;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
import com.android.quickstep.RecentsView;

@@ -29,7 +31,7 @@ import com.android.quickstep.RecentsView;
 */
public class OverviewState extends LauncherState {

    private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_MULTI_PAGE
    private static final int STATE_FLAGS = FLAG_SHOW_SCRIM
            | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED;

    public OverviewState(int id) {
@@ -38,8 +40,20 @@ public class OverviewState extends LauncherState {

    @Override
    public float[] getWorkspaceScaleAndTranslation(Launcher launcher) {
        // TODO: Find a better transition
        return new float[] {0f, 0};
        Rect pageRect = new Rect();
        RecentsView.getPageRect(launcher, pageRect);
        Workspace ws = launcher.getWorkspace();
        float childWidth = ws.getNormalChildWidth();
        if (childWidth <= 0 || pageRect.isEmpty()) {
            return super.getWorkspaceScaleAndTranslation(launcher);
        }

        Rect insets = launcher.getDragLayer().getInsets();
        float scale = pageRect.width() / childWidth;

        float halfHeight = ws.getHeight() / 2;
        float childTop = halfHeight - scale * (halfHeight - ws.getPaddingTop() - insets.top);
        return new float[] {scale, pageRect.top - childTop};
    }

    @Override
+61 −9
Original line number Diff line number Diff line
@@ -15,39 +15,91 @@
 */
package com.android.launcher3.uioverrides;

import static com.android.launcher3.WorkspaceStateTransitionAnimation.NO_ANIM_PROPERTY_SETTER;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.view.View;

import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.LauncherStateManager.StateHandler;
import com.android.launcher3.WorkspaceStateTransitionAnimation.AnimatedPropertySetter;
import com.android.launcher3.WorkspaceStateTransitionAnimation.PropertySetter;
import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsView;

public class RecentsViewStateController implements StateHandler {

    private final Launcher mLauncher;
    private final RecentsView mRecentsView;

    private final AnimatedFloat mTransitionProgress = new AnimatedFloat(this::applyProgress);
    // The fraction representing the visibility of the RecentsView. This allows delaying the
    // overall transition while the RecentsView is being shown or hidden.
    private final AnimatedFloat mVisibilityMultiplier = new AnimatedFloat(this::applyProgress);

    public RecentsViewStateController(Launcher launcher) {
        mLauncher = launcher;
        mRecentsView = launcher.getOverviewPanel();
        mRecentsView.setStateController(this);
    }

    @Override
    public void setState(LauncherState state) {
        setState(state, NO_ANIM_PROPERTY_SETTER);
        setVisibility(state == LauncherState.OVERVIEW);
        setTransitionProgress(state == LauncherState.OVERVIEW ? 1 : 0);
    }

    @Override
    public void setStateWithAnimation(LauncherState toState, AnimationLayerSet layerViews,
            AnimatorSet anim, AnimationConfig config) {
        setState(toState, new AnimatedPropertySetter(config.duration, layerViews, anim));
        ObjectAnimator progressAnim =
                mTransitionProgress.animateToValue(toState == LauncherState.OVERVIEW ? 1 : 0);
        progressAnim.setDuration(config.duration);
        progressAnim.setInterpolator(Interpolators.LINEAR);
        anim.play(progressAnim);

        ObjectAnimator visibilityAnim = animateVisibility(toState == LauncherState.OVERVIEW);
        visibilityAnim.setDuration(config.duration);
        visibilityAnim.setInterpolator(Interpolators.LINEAR);
        anim.play(visibilityAnim);
    }

    public void setVisibility(boolean isVisible) {
        mVisibilityMultiplier.cancelAnimation();
        mRecentsView.setVisibility(isVisible ? View.VISIBLE : View.GONE);
        mVisibilityMultiplier.updateValue(isVisible ? 1 : 0);
    }

    public ObjectAnimator animateVisibility(boolean isVisible) {
        ObjectAnimator anim = mVisibilityMultiplier.animateToValue(isVisible ? 1 : 0);
        if (isVisible) {
            anim.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    mRecentsView.setVisibility(View.VISIBLE);
                }
            });
        } else {
            anim.addListener(new AnimationSuccessListener() {
                @Override
                public void onAnimationSuccess(Animator animator) {
                    mRecentsView.setVisibility(View.GONE);
                }
            });
        }
        return anim;
    }

    public void setTransitionProgress(float progress) {
        mTransitionProgress.cancelAnimation();
        mTransitionProgress.updateValue(progress);
    }

    private void setState(LauncherState state, PropertySetter setter) {
        setter.setViewAlpha(null, mLauncher.getOverviewPanel(),
                state == LauncherState.OVERVIEW ? 1 : 0);
    private void applyProgress() {
        mRecentsView.setAlpha(mTransitionProgress.value * mVisibilityMultiplier.value);
    }
}
+7 −3
Original line number Diff line number Diff line
@@ -47,9 +47,7 @@ public class AnimatedFloat {
    }

    public ObjectAnimator animateToValue(float v) {
        if (mValueAnimator != null) {
            mValueAnimator.cancel();
        }
        cancelAnimation();
        mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, v);
        mValueAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
@@ -73,6 +71,12 @@ public class AnimatedFloat {
        }
    }

    public void cancelAnimation() {
        if (mValueAnimator != null) {
            mValueAnimator.cancel();
        }
    }

    public ObjectAnimator getCurrentAnimation() {
        return mValueAnimator;
    }
+15 −16
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.states.InternalStateHandler;
import com.android.launcher3.uioverrides.RecentsViewStateController;
import com.android.launcher3.util.TraceHelper;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.shared.recents.model.Task;
@@ -94,6 +95,7 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
    private Launcher mLauncher;
    private SnapshotDragView mDragView;
    private RecentsView mRecentsView;
    private RecentsViewStateController mStateController;
    private Hotseat mHotseat;
    private RecentsTaskLoadPlan mLoadPlan;

@@ -178,11 +180,13 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
        mDragView.setPivotX(0);
        mDragView.setPivotY(0);
        mRecentsView = mLauncher.getOverviewPanel();
        mStateController = mRecentsView.getStateController();
        mHotseat = mLauncher.getHotseat();

        // Optimization
        mLauncher.getAppsView().setVisibility(View.GONE);
        mRecentsView.setVisibility(View.GONE);
        mStateController.setTransitionProgress(1);
        mStateController.setVisibility(false);
        TraceHelper.partitionSection("TouchInt", "Launcher on new intent");
    }

@@ -209,17 +213,9 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {
        }

        if (mTargetRect.isEmpty()) {
            RecentsView.getPageRect(mLauncher, mTargetRect);
            DragLayer dl = mLauncher.getDragLayer();
            mSourceRect.set(0, 0, dl.getWidth(), dl.getHeight());
            Rect targetPadding = RecentsView.getPadding(mLauncher);
            Rect insets = dl.getInsets();
            mTargetRect.set(
                    targetPadding.left + insets.left,
                    targetPadding.top + insets.top,
                    mSourceRect.right - targetPadding.right - insets.right,
                    mSourceRect.bottom - targetPadding.bottom - insets.bottom);
            mTargetRect.top += mLauncher.getResources()
                    .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
        }

        float shift = mCurrentShift.value * mActivityMultiplier.value;
@@ -246,12 +242,15 @@ public class NavBarSwipeInteractionHandler extends InternalStateHandler {

    private void setTaskPlanToUi() {
        mRecentsView.update(mLoadPlan);
        mRecentsView.setVisibility(View.VISIBLE);

        // Animate alpha
        mRecentsView.setAlpha(0);
        mRecentsView.animate().alpha(1).setDuration(RECENTS_VIEW_VISIBILITY_DURATION)
                .withEndAction(() -> mStateCallback.setState(STATE_RECENTS_FULLY_VISIBLE));
        ObjectAnimator anim = mStateController.animateVisibility(true /* isVisible */)
                .setDuration(RECENTS_VIEW_VISIBILITY_DURATION);
        anim.addListener(new AnimationSuccessListener() {
            @Override
            public void onAnimationSuccess(Animator animator) {
                mStateCallback.setState(STATE_RECENTS_FULLY_VISIBLE);
            }
        });
        anim.start();
    }

    @UiThread
Loading