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

Commit 787e9dd6 authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Implement transition for docking task in recents #5

- Move task along a curved path.

Bug: 27607141
Change-Id: I945071de55efed0d327b68045e48fea6989adf63
parent 8448f339
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -29,8 +29,9 @@ import android.util.Log;
 * This class holds a collection of Keyframe objects and is called by ValueAnimator to calculate
 * values between those keyframes for a given animation. The class internal to the animation
 * package because it is an implementation detail of how Keyframes are stored and used.
 * @hide
 */
class KeyframeSet implements Keyframes {
public class KeyframeSet implements Keyframes {

    int mNumKeyframes;

+2 −1
Original line number Diff line number Diff line
@@ -34,8 +34,9 @@ import java.util.ArrayList;
 * Typically, the returned type is a PointF, but the individual components can be extracted
 * as either an IntKeyframes or FloatKeyframes.
 * </p>
 * @hide
 */
class PathKeyframes implements Keyframes {
public class PathKeyframes implements Keyframes {
    private static final int FRACTION_OFFSET = 0;
    private static final int X_OFFSET = 1;
    private static final int Y_OFFSET = 2;
+65 −24
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Debug;
import android.os.IBinder;
@@ -71,11 +72,13 @@ import android.view.animation.PathInterpolator;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;

import com.android.internal.R;
import com.android.internal.util.DumpUtils.Dump;
import com.android.server.AttributeCache;
import com.android.server.wm.WindowManagerService.H;
import com.android.server.wm.animation.ClipRectLRAnimation;
import com.android.server.wm.animation.ClipRectTBAnimation;
import com.android.server.wm.animation.CurvedTranslateAnimation;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -150,7 +153,6 @@ public class AppTransition implements Dump {
     */
    private static final int MAX_CLIP_REVEAL_TRANSITION_DURATION = 420;
    private static final int THUMBNAIL_APP_TRANSITION_DURATION = 336;
    private static final int THUMBNAIL_APP_TRANSITION_ALPHA_DURATION = 336;
    private static final long APP_TRANSITION_TIMEOUT_MS = 5000;

    private final Context mContext;
@@ -211,6 +213,7 @@ public class AppTransition implements Dump {
    private final Interpolator mThumbnailFadeOutInterpolator;
    private final Interpolator mLinearOutSlowInInterpolator;
    private final Interpolator mFastOutLinearInInterpolator;
    private final Interpolator mFastOutSlowInInterpolator;
    private final Interpolator mClipHorizontalInterpolator = new PathInterpolator(0, 0, 0.4f, 1f);

    private final int mClipRevealTranslationY;
@@ -231,6 +234,8 @@ public class AppTransition implements Dump {
                com.android.internal.R.interpolator.linear_out_slow_in);
        mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.fast_out_linear_in);
        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.fast_out_slow_in);
        mConfigShortAnimTime = context.getResources().getInteger(
                com.android.internal.R.integer.config_shortAnimTime);
        mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
@@ -817,7 +822,7 @@ public class AppTransition implements Dump {
     * Prepares the specified animation with a standard duration, interpolator, etc.
     */
    Animation prepareThumbnailAnimationWithDuration(Animation a, int appWidth, int appHeight,
            int duration, Interpolator interpolator) {
            long duration, Interpolator interpolator) {
        if (duration > 0) {
            a.setDuration(duration);
        }
@@ -887,17 +892,19 @@ public class AppTransition implements Dump {
        final float fromX = mTmpRect.left;
        final float pivotX = mTmpRect.width() / 2;
        final float pivotY = mTmpRect.height() / 2;
        final long duration = getAspectScaleDuration();
        final Interpolator interpolator = getAspectScaleInterpolator();
        if (mNextAppTransitionScaleUp) {
            // Animation up from the thumbnail to the full screen
            Animation scale = new ScaleAnimation(1f, scaleW, 1f, scaleW, pivotX, pivotY);
            scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
            scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
            scale.setInterpolator(interpolator);
            scale.setDuration(duration);
            Animation alpha = new AlphaAnimation(1f, 0f);
            alpha.setInterpolator(mThumbnailFadeOutInterpolator);
            alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
            Animation translate = new TranslateAnimation(fromX, toX, fromY, toY);
            translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
            translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
            alpha.setDuration(duration);
            Animation translate = createCurvedMotion(fromX, toX, fromY, toY);
            translate.setInterpolator(interpolator);
            translate.setDuration(duration);

            mTmpFromClipRect.set(0, 0, thumbWidthI, thumbHeightI);
            mTmpToClipRect.set(appRect);
@@ -916,8 +923,8 @@ public class AppTransition implements Dump {
            }

            Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
            clipAnim.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
            clipAnim.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
            clipAnim.setInterpolator(interpolator);
            clipAnim.setDuration(duration);

            // This AnimationSet uses the Interpolators assigned above.
            AnimationSet set = new AnimationSet(false);
@@ -929,14 +936,14 @@ public class AppTransition implements Dump {
        } else {
            // Animation down from the full screen to the thumbnail
            Animation scale = new ScaleAnimation(scaleW, 1f, scaleW, 1f, pivotX, pivotY);
            scale.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
            scale.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
            scale.setInterpolator(interpolator);
            scale.setDuration(duration);
            Animation alpha = new AlphaAnimation(0f, 1f);
            alpha.setInterpolator(mThumbnailFadeInInterpolator);
            alpha.setDuration(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION);
            Animation translate = new TranslateAnimation(toX, fromX, toY, fromY);
            translate.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR);
            translate.setDuration(THUMBNAIL_APP_TRANSITION_DURATION);
            alpha.setDuration(duration);
            Animation translate = createCurvedMotion(toX, fromX, toY, fromY);
            translate.setInterpolator(interpolator);
            translate.setDuration(duration);

            // This AnimationSet uses the Interpolators assigned above.
            AnimationSet set = new AnimationSet(false);
@@ -950,6 +957,40 @@ public class AppTransition implements Dump {
                TOUCH_RESPONSE_INTERPOLATOR);
    }

    private Animation createCurvedMotion(float fromX, float toX, float fromY, float toY) {

        // Almost no x-change - use linear animation
        if (Math.abs(toX - fromX) < 1f) {
            return new TranslateAnimation(fromX, toX, fromY, toY);
        } else {
            final Path path = createCurvedPath(fromX, toX, fromY, toY);
            return new CurvedTranslateAnimation(path);
        }
    }

    private Path createCurvedPath(float fromX, float toX, float fromY, float toY) {
        final Path path = new Path();
        path.moveTo(fromX, fromY);
        path.cubicTo(fromX, fromY, toX, 0.9f * fromY + 0.1f * toY, toX, toY);
        return path;
    }

    private long getAspectScaleDuration() {
        if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
            return (long) (THUMBNAIL_APP_TRANSITION_DURATION * 1f);
        } else {
            return THUMBNAIL_APP_TRANSITION_DURATION;
        }
    }

    private Interpolator getAspectScaleInterpolator() {
        if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS) {
            return mFastOutSlowInInterpolator;
        } else {
            return TOUCH_RESPONSE_INTERPOLATOR;
        }
    }

    /**
     * This alternate animation is created when we are doing a thumbnail transition, for the
     * activity that is leaving, and the activity that is entering.
@@ -1017,8 +1058,8 @@ public class AppTransition implements Dump {
                                ? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect)
                                : new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect);
                        Animation translateAnim = scaleUp
                                ? new TranslateAnimation(startX, 0, startY - scaledTopDecor, 0)
                                : new TranslateAnimation(0, startX, 0, startY - scaledTopDecor);
                                ? createCurvedMotion(startX, 0, startY - scaledTopDecor, 0)
                                : createCurvedMotion(0, startX, 0, startY - scaledTopDecor);
                        set.addAnimation(clipAnim);
                        set.addAnimation(scaleAnim);
                        set.addAnimation(translateAnim);
@@ -1032,8 +1073,10 @@ public class AppTransition implements Dump {
                                ? new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect)
                                : new ClipRectAnimation(mTmpToClipRect, mTmpFromClipRect);
                        Animation translateAnim = scaleUp
                                ? new TranslateAnimation(thumbStartX, 0, thumbStartY - contentInsets.top, 0)
                                : new TranslateAnimation(0, thumbStartX, 0, thumbStartY - contentInsets.top);
                                ? createCurvedMotion(thumbStartX, 0,
                                thumbStartY - contentInsets.top, 0)
                                : createCurvedMotion(0, thumbStartX, 0,
                                        thumbStartY - contentInsets.top);

                        set.addAnimation(clipAnim);
                        set.addAnimation(translateAnim);
@@ -1070,10 +1113,8 @@ public class AppTransition implements Dump {
                throw new RuntimeException("Invalid thumbnail transition state");
        }

        int duration = Math.max(THUMBNAIL_APP_TRANSITION_ALPHA_DURATION,
                THUMBNAIL_APP_TRANSITION_DURATION);
        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight, duration,
                TOUCH_RESPONSE_INTERPOLATOR);
        return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
                getAspectScaleDuration(), getAspectScaleInterpolator());
    }

    private Animation createAspectScaledThumbnailEnterFreeformAnimationLocked(Rect frame,
+42 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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
 */

package com.android.server.wm.animation;

import android.animation.KeyframeSet;
import android.animation.PathKeyframes;
import android.graphics.Path;
import android.graphics.PointF;
import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * Translate animation which follows a curved path.
 */
public class CurvedTranslateAnimation extends Animation {

    private final PathKeyframes mKeyframes;

    public CurvedTranslateAnimation(Path path) {
        mKeyframes = KeyframeSet.ofPath(path);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        PointF location = (PointF) mKeyframes.getValue(interpolatedTime);
        t.getMatrix().setTranslate(location.x, location.y);
    }
}