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

Commit 6fd105b6 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Updating gesture tutorial home animation

> Using a separate View as icon, instead of the taskView
> Updating swipe animation logic to abstract out FloatingIconView dependency

Change-Id: Ib466262afead11ebe4ca035d589f0382c37e3e97
parent b82121c0
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -140,7 +140,6 @@ public class FallbackSwipeHandler extends

        private final long mDuration;
        FallbackHomeAnimationFactory(long duration) {
            super(null);
            mDuration = duration;

            if (mRunningOverHome) {
+47 −24
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.quickstep;

import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;

import android.animation.AnimatorSet;
import android.content.Context;
@@ -28,6 +29,7 @@ import androidx.annotation.NonNull;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.StaggeredWorkspaceAnim;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
@@ -72,36 +74,39 @@ public class LauncherSwipeHandlerV2 extends
            mActivity.getRootView().setForceHideBackArrow(true);
            mActivity.setHintUserWillBeActive();

            homeAnimFactory = new HomeAnimationFactory(floatingIconView) {

            if (canUseWorkspaceView) {
                // We want the window alpha to be 0 once this threshold is met, so that the
                // FolderIconView can be seen morphing into the icon shape.
                float windowAlphaThreshold = 1f - SHAPE_PROGRESS_DURATION;
                homeAnimFactory = new LauncherHomeAnimationFactory() {
                    @Override
                    public RectF getWindowTargetRect() {
                    if (canUseWorkspaceView) {
                        return iconLocation;
                    } else {
                        return super.getWindowTargetRect();
                    }

                    @Override
                    public void setAnimation(RectFSpringAnim anim) {
                        anim.addAnimatorListener(floatingIconView);
                        floatingIconView.setOnTargetChangeListener(anim::onTargetPositionChanged);
                        floatingIconView.setFastFinishRunnable(anim::end);
                    }

                @NonNull
                    @Override
                public AnimatorPlaybackController createActivityAnimationToHome() {
                    // Return an empty APC here since we have an non-user controlled animation
                    // to home.
                    long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
                    return mActivity.getStateManager().createAnimationToNewWorkspace(
                            NORMAL, accuracy, 0 /* animComponents */);
                    public void update(RectF currentRect, float progress, float radius) {
                        floatingIconView.update(currentRect, 1f, progress, windowAlphaThreshold,
                                radius, false);
                    }

                    @Override
                public void playAtomicAnimation(float velocity) {
                    new StaggeredWorkspaceAnim(mActivity, velocity,
                            true /* animateOverviewScrim */).start();
                    public void onCancel() {
                        floatingIconView.fastFinish();
                    }
                };

            } else {
            homeAnimFactory = new HomeAnimationFactory(null) {
                homeAnimFactory = new LauncherHomeAnimationFactory();
            }
        } else {
            homeAnimFactory = new HomeAnimationFactory() {
                @Override
                public AnimatorPlaybackController createActivityAnimationToHome() {
                    return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
@@ -118,4 +123,22 @@ public class LauncherSwipeHandlerV2 extends
        mRecentsAnimationController.finish(
                true /* toRecents */, callback, true /* sendUserLeaveHint */);
    }

    private class LauncherHomeAnimationFactory extends HomeAnimationFactory {
        @NonNull
        @Override
        public AnimatorPlaybackController createActivityAnimationToHome() {
            // Return an empty APC here since we have an non-user controlled animation
            // to home.
            long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
            return mActivity.getStateManager().createAnimationToNewWorkspace(
                    NORMAL, accuracy, 0 /* animComponents */);
        }

        @Override
        public void playAtomicAnimation(float velocity) {
            new StaggeredWorkspaceAnim(mActivity, velocity,
                    true /* animateOverviewScrim */).start();
        }
    }
}
+11 −30
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package com.android.quickstep;

import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;

import android.animation.Animator;
import android.content.Context;
@@ -28,7 +27,6 @@ import android.graphics.RectF;
import android.view.animation.Interpolator;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;

import com.android.launcher3.DeviceProfile;
@@ -37,7 +35,6 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.views.FloatingIconView;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.TaskViewSimulator;
import com.android.quickstep.util.TransformParams;
@@ -148,12 +145,6 @@ public abstract class SwipeUpAnimationLogic {

    protected abstract class HomeAnimationFactory {

        public FloatingIconView mIconView;

        public HomeAnimationFactory(@Nullable FloatingIconView iconView) {
            mIconView = iconView;
        }

        public @NonNull RectF getWindowTargetRect() {
            PagedOrientationHandler orientationHandler = getOrientationHandler();
            DeviceProfile dp = mDp;
@@ -174,6 +165,12 @@ public abstract class SwipeUpAnimationLogic {
        public void playAtomicAnimation(float velocity) {
            // No-op
        }

        public void setAnimation(RectFSpringAnim anim) { }

        public void update(RectF currentRect, float progress, float radius) { }

        public void onCancel() { }
    }

    /**
@@ -184,8 +181,6 @@ public abstract class SwipeUpAnimationLogic {
    protected RectFSpringAnim createWindowAnimationToHome(float startProgress,
            HomeAnimationFactory homeAnimationFactory) {
        final RectF targetRect = homeAnimationFactory.getWindowTargetRect();
        final FloatingIconView fiv = homeAnimationFactory.mIconView;
        final boolean isFloatingIconView = fiv != null;

        mWindowTransitionController.setPlayFraction(startProgress / mDragLengthFactor);
        mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
@@ -203,11 +198,7 @@ public abstract class SwipeUpAnimationLogic {
        windowToHomePositionMap.mapRect(startRect);

        RectFSpringAnim anim = new RectFSpringAnim(startRect, targetRect, mContext);
        if (isFloatingIconView) {
            anim.addAnimatorListener(fiv);
            fiv.setOnTargetChangeListener(anim::onTargetPositionChanged);
            fiv.setFastFinishRunnable(anim::end);
        }
        homeAnimationFactory.setAnimation(anim);

        SpringAnimationRunner runner = new SpringAnimationRunner(
                homeAnimationFactory, cropRectF, homeToWindowPositionMap);
@@ -242,32 +233,27 @@ public abstract class SwipeUpAnimationLogic {

        final RectF mWindowCurrentRect = new RectF();
        final Matrix mHomeToWindowPositionMap;
        final HomeAnimationFactory mAnimationFactory;

        final FloatingIconView mFIV;
        final AnimatorPlaybackController mHomeAnim;
        final RectF mCropRectF;

        final float mStartRadius;
        final float mEndRadius;
        final float mWindowAlphaThreshold;

        SpringAnimationRunner(HomeAnimationFactory factory, RectF cropRectF,
                Matrix homeToWindowPositionMap) {
            mAnimationFactory = factory;
            mHomeAnim = factory.createActivityAnimationToHome();
            mCropRectF = cropRectF;
            mHomeToWindowPositionMap = homeToWindowPositionMap;

            cropRectF.roundOut(mCropRect);
            mFIV = factory.mIconView;

            // End on a "round-enough" radius so that the shape reveal doesn't have to do too much
            // rounding at the end of the animation.
            mStartRadius = mTaskViewSimulator.getCurrentCornerRadius();
            mEndRadius = cropRectF.width() / 2f;

            // We want the window alpha to be 0 once this threshold is met, so that the
            // FolderIconView can be seen morphing into the icon shape.
            mWindowAlphaThreshold = mFIV != null ? 1f - SHAPE_PROGRESS_DURATION : 1f;
        }

        @Override
@@ -282,10 +268,7 @@ public abstract class SwipeUpAnimationLogic {
                    .setCornerRadius(cornerRadius);

            mTransformParams.applySurfaceParams(mTransformParams.createSurfaceParams(this));
            if (mFIV != null) {
                mFIV.update(currentRect, 1f, progress,
                        mWindowAlphaThreshold, mMatrix.mapRadius(cornerRadius), false);
            }
            mAnimationFactory.update(currentRect, progress, mMatrix.mapRadius(cornerRadius));
        }

        @Override
@@ -298,9 +281,7 @@ public abstract class SwipeUpAnimationLogic {

        @Override
        public void onCancel() {
            if (mFIV != null) {
                mFIV.fastFinish();
            }
            mAnimationFactory.onCancel();
        }

        @Override
+20 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
    Copyright (C) 2020 The Android Open Source Project

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="#FFFFFFFF" />
</shape>
 No newline at end of file
+31 −23
Original line number Diff line number Diff line
@@ -24,6 +24,14 @@
        android:layout_height="match_parent"
        android:background="@drawable/gesture_tutorial_ripple"/>

    <com.android.launcher3.views.ClipIconView
        android:id="@+id/gesture_tutorial_fake_icon_view"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:background="@drawable/bg_circle"
        android:backgroundTint="@color/gesture_tutorial_fake_task_view_color"
        android:visibility="invisible" />

    <View
        android:id="@+id/gesture_tutorial_fake_task_view"
        android:layout_width="match_parent"
@@ -41,81 +49,81 @@
        android:id="@+id/gesture_tutorial_fragment_close_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="18dp"
        android:layout_marginTop="30dp"
        android:layout_marginStart="4dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:background="@android:color/transparent"
        android:layout_marginStart="4dp"
        android:layout_marginTop="30dp"
        android:accessibilityTraversalAfter="@id/gesture_tutorial_fragment_titles_container"
        android:background="@android:color/transparent"
        android:contentDescription="@string/gesture_tutorial_close_button_content_description"
        android:tint="?android:attr/textColorPrimary"
        android:src="@drawable/gesture_tutorial_close_button"/>
        android:padding="18dp"
        android:src="@drawable/gesture_tutorial_close_button"
        android:tint="?android:attr/textColorPrimary"/>

    <LinearLayout
        android:id="@+id/gesture_tutorial_fragment_titles_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="70dp"
        android:layout_alignParentTop="true"
        android:layout_marginTop="70dp"
        android:focusable="true"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <TextView
            android:id="@+id/gesture_tutorial_fragment_title_view"
            style="@style/TextAppearance.GestureTutorial.Title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/gesture_tutorial_title_margin_start_end"
            android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"
            style="@style/TextAppearance.GestureTutorial.Title"/>
            android:layout_marginEnd="@dimen/gesture_tutorial_title_margin_start_end"/>

        <TextView
            android:id="@+id/gesture_tutorial_fragment_subtitle_view"
            style="@style/TextAppearance.GestureTutorial.Subtitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:layout_marginStart="@dimen/gesture_tutorial_subtitle_margin_start_end"
            android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"
            style="@style/TextAppearance.GestureTutorial.Subtitle"/>
            android:layout_marginTop="10dp"
            android:layout_marginEnd="@dimen/gesture_tutorial_subtitle_margin_start_end"/>
    </LinearLayout>

    <TextView
        android:id="@+id/gesture_tutorial_fragment_feedback_view"
        style="@style/TextAppearance.GestureTutorial.Feedback"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="10dp"
        android:layout_centerHorizontal="true"
        android:layout_above="@id/gesture_tutorial_fragment_action_button"
        android:layout_centerHorizontal="true"
        android:layout_marginStart="@dimen/gesture_tutorial_feedback_margin_start_end"
        android:layout_marginEnd="@dimen/gesture_tutorial_feedback_margin_start_end"
        style="@style/TextAppearance.GestureTutorial.Feedback"/>
        android:layout_marginBottom="10dp"/>

    <!-- android:stateListAnimator="@null" removes shadow and normal on click behavior (increase
         of elevation and shadow) which is replaced by ripple effect in android:foreground -->
    <Button
        android:id="@+id/gesture_tutorial_fragment_action_button"
        style="@style/TextAppearance.GestureTutorial.ButtonLabel"
        android:layout_width="142dp"
        android:layout_height="49dp"
        android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
        android:layout_marginBottom="48dp"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"
        android:stateListAnimator="@null"
        android:layout_marginEnd="@dimen/gesture_tutorial_button_margin_start_end"
        android:layout_marginBottom="48dp"
        android:background="@drawable/gesture_tutorial_action_button_background"
        android:foreground="?android:attr/selectableItemBackgroundBorderless"
        style="@style/TextAppearance.GestureTutorial.ButtonLabel"/>
        android:stateListAnimator="@null"/>

    <Button
        android:id="@+id/gesture_tutorial_fragment_action_text_button"
        style="@style/TextAppearance.GestureTutorial.TextButtonLabel"
        android:layout_width="142dp"
        android:layout_height="49dp"
        android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
        android:layout_marginBottom="48dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true"
        android:stateListAnimator="@null"
        android:layout_marginStart="@dimen/gesture_tutorial_button_margin_start_end"
        android:layout_marginBottom="48dp"
        android:background="@null"
        android:foreground="?android:attr/selectableItemBackgroundBorderless"
        style="@style/TextAppearance.GestureTutorial.TextButtonLabel"/>
        android:stateListAnimator="@null"/>
</RelativeLayout>
 No newline at end of file
Loading