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

Commit 4831c749 authored by Bobby Georgescu's avatar Bobby Georgescu
Browse files

Big refactor, additions to state transition animations

Bug: 7362944
Refactored a lot of the state transitions code, adding
support for definable transition animations and defining
distinct outgoing and incoming animations.
Change-Id: I31a69057ea1b72dd3185cec656e59b11fdb528c1
parent 43b906d8
Loading
Loading
Loading
Loading
+108 −30
Original line number Diff line number Diff line
@@ -17,61 +17,139 @@
package com.android.gallery3d.anim;

import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;

import com.android.gallery3d.ui.GLCanvas;
import com.android.gallery3d.ui.GLView;
import com.android.gallery3d.ui.RawTexture;
import com.android.gallery3d.ui.TiledScreenNail;

public class StateTransitionAnimation extends Animation {
    private static final float BACKGROUND_ALPHA_FROM = 1f;
    private static final float BACKGROUND_ALPHA_TO = 0f;
    private static final float BACKGROUND_SCALE_FROM = 1f;
    private static final float BACKGROUND_SCALE_TO = 0f;
    private static final float FOREGROUND_ALPHA_FROM = 0.9f;
    private static final float FOREGROUND_ALPHA_TO = 1f;
    private static final float FOREGROUND_SCALE_FROM = 3f;
    private static final float FOREGROUND_SCALE_TO = 1f;

    private float mCurrentForegroundScale;

    public static class Spec {
        public static final Spec OUTGOING;
        public static final Spec INCOMING;

        public int duration = 330;
        public float backgroundAlphaFrom = 0;
        public float backgroundAlphaTo = 0;
        public float backgroundScaleFrom = 0;
        public float backgroundScaleTo = 0;
        public float contentAlphaFrom = 1;
        public float contentAlphaTo = 1;
        public float contentScaleFrom = 1;
        public float contentScaleTo = 1;
        public float overlayAlphaFrom = 0;
        public float overlayAlphaTo = 0;
        public float overlayScaleFrom = 0;
        public float overlayScaleTo = 0;
        public Interpolator interpolator;

        static {
            OUTGOING = new Spec();
            OUTGOING.backgroundAlphaFrom = 1f;
            OUTGOING.backgroundAlphaTo = 0f;
            OUTGOING.backgroundScaleFrom = 1f;
            OUTGOING.backgroundScaleTo = 0f;
            OUTGOING.contentAlphaFrom = 0.9f;
            OUTGOING.contentAlphaTo = 1f;
            OUTGOING.contentScaleFrom = 3f;
            OUTGOING.contentScaleTo = 1f;
            OUTGOING.interpolator = new DecelerateInterpolator();

            INCOMING = new Spec();
            INCOMING.overlayAlphaFrom = 1f;
            INCOMING.overlayAlphaTo = 0f;
            INCOMING.overlayScaleFrom = 1f;
            INCOMING.overlayScaleTo = 3f;
            INCOMING.contentAlphaFrom = 0f;
            INCOMING.contentAlphaTo = 1f;
            INCOMING.contentScaleFrom = 0.25f;
            INCOMING.contentScaleTo = 1f;
            INCOMING.interpolator = new DecelerateInterpolator();
        }
    }

    private final Spec mTransitionSpec;
    private float mCurrentContentScale;
    private float mCurrentContentAlpha;
    private float mCurrentBackgroundScale;
    private float mCurrentBackgroundAlpha;
    private float mCurrentForegroundAlpha;
    private float mCurrentOverlayScale;
    private float mCurrentOverlayAlpha;
    private RawTexture mOldScreenTexture;

    public StateTransitionAnimation(Spec spec, RawTexture oldScreen) {
        mTransitionSpec = spec != null ? spec : Spec.OUTGOING;
        setDuration(mTransitionSpec.duration);
        setInterpolator(mTransitionSpec.interpolator);
        mOldScreenTexture = oldScreen;
        if (mOldScreenTexture != null) {
            TiledScreenNail.disableDrawPlaceholder();
        }
    }

    public StateTransitionAnimation(int duration) {
        setDuration(duration);
        setInterpolator(new DecelerateInterpolator());
    @Override
    public boolean calculate(long currentTimeMillis) {
        boolean retval = super.calculate(currentTimeMillis);
        if (mOldScreenTexture != null && !isActive()) {
            mOldScreenTexture.recycle();
            mOldScreenTexture = null;
            TiledScreenNail.enableDrawPlaceholder();
        }
        return retval;
    }

    @Override
    protected void onCalculate(float progress) {
        mCurrentForegroundScale = FOREGROUND_SCALE_FROM
                + (FOREGROUND_SCALE_TO - FOREGROUND_SCALE_FROM) * progress;
        mCurrentForegroundAlpha = FOREGROUND_ALPHA_FROM
                + (FOREGROUND_ALPHA_TO - FOREGROUND_ALPHA_FROM) * progress;
        mCurrentBackgroundAlpha = BACKGROUND_ALPHA_FROM
                + (BACKGROUND_ALPHA_TO - BACKGROUND_ALPHA_FROM) * progress;
        mCurrentBackgroundScale = BACKGROUND_SCALE_FROM
                + (BACKGROUND_SCALE_TO - BACKGROUND_SCALE_FROM) * progress;
        mCurrentContentScale = mTransitionSpec.contentScaleFrom
                + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress;
        mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom
                + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress;
        mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom
                + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom)
                * progress;
        mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom
                + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom)
                * progress;
        mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom
                + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress;
        mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom
                + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress;
    }

    public void applyBackground(GLView view, GLCanvas canvas, RawTexture fadeTexture) {
        canvas.clearBuffer(view.getBackgroundColor());
    private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) {
        if (mOldScreenTexture == null)
            return;
        if (clear) canvas.clearBuffer(view.getBackgroundColor());
        canvas.save();
        canvas.setAlpha(mCurrentBackgroundAlpha);
        canvas.setAlpha(alpha);
        int xOffset = view.getWidth() / 2;
        int yOffset = view.getHeight() / 2;
        canvas.translate(xOffset, yOffset);
        canvas.scale(mCurrentBackgroundScale, mCurrentBackgroundScale, 1);
        fadeTexture.draw(canvas, -xOffset, -yOffset);
        canvas.scale(scale, scale, 1);
        mOldScreenTexture.draw(canvas, -xOffset, -yOffset);
        canvas.restore();
    }

    public void applyForegroundTransformation(GLView view, GLCanvas canvas) {
    public void applyBackground(GLView view, GLCanvas canvas) {
        if (mCurrentBackgroundAlpha > 0f) {
            applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true);
        }
    }

    public void applyContentTransform(GLView view, GLCanvas canvas) {
        int xOffset = view.getWidth() / 2;
        int yOffset = view.getHeight() / 2;
        canvas.translate(xOffset, yOffset);
        canvas.scale(mCurrentForegroundScale, mCurrentForegroundScale, 1);
        canvas.scale(mCurrentContentScale, mCurrentContentScale, 1);
        canvas.translate(-xOffset, -yOffset);
        canvas.setAlpha(mCurrentForegroundAlpha);
        canvas.setAlpha(mCurrentContentAlpha);
    }

    public void applyOverlay(GLView view, GLCanvas canvas) {
        if (mCurrentOverlayAlpha > 0f) {
            applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false);
        }
    }
}
+29 −18
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.view.Window;
import android.view.WindowManager;

import com.android.gallery3d.R;
import com.android.gallery3d.anim.StateTransitionAnimation;
import com.android.gallery3d.ui.GLView;
import com.android.gallery3d.ui.PreparePageFadeoutTexture;
import com.android.gallery3d.ui.RawTexture;
@@ -70,19 +71,19 @@ abstract public class ActivityState {

    private static final String KEY_TRANSITION_IN = "transition-in";

    private RawTexture mFadeOutTexture;
    public static enum StateTransition { None, Outgoing, Incoming };
    private StateTransition mNextTransition = StateTransition.None;
    private StateTransitionAnimation mIntroAnimation;
    private GLView mContentPane;
    private boolean mWantFadeOut = false;
    private boolean mTransitionIn;

    protected ActivityState() {
    }

    protected void setContentPane(GLView content) {
        mContentPane = content;
        if (mTransitionIn) {
            mContentPane.setFadeOutTexture(mFadeOutTexture);
            mFadeOutTexture = null;
        if (mNextTransition != StateTransition.None) {
            mContentPane.setIntroAnimation(mIntroAnimation);
            mIntroAnimation = null;
        }
        mContentPane.setBackgroundColor(getBackgroundColor());
        mActivity.getGLRoot().setContentPane(mContentPane);
@@ -99,9 +100,6 @@ abstract public class ActivityState {
    }

    protected void onBackPressed() {
        if (mActivity.getStateManager().getStateCount() > 1) {
            fadeOutOnNextPause();
        }
        mActivity.getStateManager().finishState(this);
    }

@@ -175,19 +173,25 @@ abstract public class ActivityState {
        win.setAttributes(params);
    }

    protected void fadeOutOnNextPause() {
        mWantFadeOut = true;
    protected void transitionOnNextPause(Class<? extends ActivityState> outgoing,
            Class<? extends ActivityState> incoming, StateTransition hint) {
        if (outgoing == PhotoPage.class && incoming == AlbumPage.class) {
            mNextTransition = StateTransition.Outgoing;
        } else if (outgoing == AlbumPage.class && incoming == PhotoPage.class) {
            mNextTransition = StateTransition.Incoming;
        } else {
            mNextTransition = hint;
        }
    }

    protected void onPause() {
        if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) {
            ((Activity) mActivity).unregisterReceiver(mPowerIntentReceiver);
        }
        if (mWantFadeOut) {
            mWantFadeOut = false;
            if (PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mContentPane)) {
                mActivity.getTransitionStore().put(KEY_TRANSITION_IN, true);
            }
        if (mNextTransition != StateTransition.None) {
            mActivity.getTransitionStore().put(KEY_TRANSITION_IN, mNextTransition);
            PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mContentPane);
            mNextTransition = StateTransition.None;
        }
    }

@@ -242,9 +246,16 @@ abstract public class ActivityState {

    // a subclass of ActivityState should override the method to resume itself
    protected void onResume() {
        mFadeOutTexture = mActivity.getTransitionStore().get(
        RawTexture fade = mActivity.getTransitionStore().get(
                PreparePageFadeoutTexture.KEY_FADE_TEXTURE);
        mTransitionIn = mActivity.getTransitionStore().get(KEY_TRANSITION_IN, false);
        mNextTransition = mActivity.getTransitionStore().get(
                KEY_TRANSITION_IN, StateTransition.None);
        if (mNextTransition != StateTransition.None) {
            mIntroAnimation = new StateTransitionAnimation(
                    (mNextTransition == StateTransition.Incoming) ?
                            StateTransitionAnimation.Spec.INCOMING :
                            StateTransitionAnimation.Spec.OUTGOING, fade);
        }
    }

    protected boolean onCreateActionBar(Menu menu) {
+14 −9
Original line number Diff line number Diff line
@@ -57,7 +57,8 @@ public class StateManager {
        }
        if (!mStack.isEmpty()) {
            ActivityState top = getTopState();
            top.fadeOutOnNextPause();
            top.transitionOnNextPause(top.getClass(), klass,
                    ActivityState.StateTransition.Incoming);
            if (mIsResumed) top.onPause();
        }
        state.initialize(mActivity, data);
@@ -82,7 +83,8 @@ public class StateManager {

        if (!mStack.isEmpty()) {
            ActivityState as = getTopState();
            as.fadeOutOnNextPause();
            as.transitionOnNextPause(as.getClass(), klass,
                    ActivityState.StateTransition.Incoming);
            as.mReceivedResults = state.mResult;
            if (mIsResumed) as.onPause();
        } else {
@@ -188,15 +190,18 @@ public class StateManager {
        // Remove the top state.
        mStack.pop();
        state.mIsFinishing = true;
        if (mIsResumed && fireOnPause) state.onPause();
        ActivityState top = !mStack.isEmpty() ? mStack.peek().activityState : null;
        if (mIsResumed && fireOnPause) {
            if (top != null) {
                state.transitionOnNextPause(state.getClass(), top.getClass(),
                        ActivityState.StateTransition.Outgoing);
            }
            state.onPause();
        }
        mActivity.getGLRoot().setContentPane(null);
        state.onDestroy();

        if (!mStack.isEmpty()) {
            // Restore the immediately previous state
            ActivityState top = mStack.peek().activityState;
            if (mIsResumed) top.resume();
        }
        if (top != null && mIsResumed) top.resume();
    }

    public void switchState(ActivityState oldState,
@@ -211,7 +216,7 @@ public class StateManager {
        mStack.pop();
        if (!data.containsKey(PhotoPage.KEY_APP_BRIDGE)) {
            // Do not do the fade out stuff when we are switching camera modes
            oldState.fadeOutOnNextPause();
            oldState.transitionOnNextPause(oldState.getClass(), klass, ActivityState.StateTransition.Incoming);
        }
        if (mIsResumed) oldState.onPause();
        oldState.onDestroy();
+19 −21
Original line number Diff line number Diff line
@@ -78,10 +78,8 @@ public class GLView {
    protected int mScrollHeight = 0;
    protected int mScrollWidth = 0;

    public static final int ANIM_TIME_OPENING = 400;
    private RawTexture mFadeOutTexture;
    private float [] mBackgroundColor;
    private StateTransitionAnimation mTransition = new StateTransitionAnimation(ANIM_TIME_OPENING);
    private StateTransitionAnimation mTransition;

    public void startAnimation(CanvasAnimation animation) {
        GLRoot root = getGLRoot();
@@ -223,22 +221,28 @@ public class GLView {
    }

    protected void render(GLCanvas canvas) {
        if (mTransition.calculate(AnimationTime.get())) invalidate();
        canvas.save();
        boolean transitionActive = false;
        if (mTransition != null && mTransition.calculate(AnimationTime.get())) {
            invalidate();
            transitionActive = mTransition.isActive();
        }
        renderBackground(canvas);
        if (mTransition.isActive()) mTransition.applyForegroundTransformation(this, canvas);
        canvas.save();
        if (transitionActive) {
            mTransition.applyContentTransform(this, canvas);
        }
        for (int i = 0, n = getComponentCount(); i < n; ++i) {
            renderChild(canvas, getComponent(i));
        }
        canvas.restore();
        if (transitionActive) {
            mTransition.applyOverlay(this, canvas);
        }

    public void setFadeOutTexture(RawTexture texture) {
        mFadeOutTexture = texture;
        if (mFadeOutTexture != null) {
            TiledScreenNail.disableDrawPlaceholder();
    }
        mTransition.start();

    public void setIntroAnimation(StateTransitionAnimation intro) {
        mTransition = intro;
        if (mTransition != null) mTransition.start();
    }

    public float [] getBackgroundColor() {
@@ -253,17 +257,11 @@ public class GLView {
        if (mBackgroundColor != null) {
            view.clearBuffer(mBackgroundColor);
        }
        if (mFadeOutTexture != null) {
            if (!mTransition.isActive()) {
                mFadeOutTexture.recycle();
                mFadeOutTexture = null;
                TiledScreenNail.enableDrawPlaceholder();
            } else {
                mTransition.applyBackground(this, view, mFadeOutTexture);
        if (mTransition != null && mTransition.isActive()) {
            mTransition.applyBackground(this, view);
            return;
        }
    }
    }

    protected void renderChild(GLCanvas canvas, GLView component) {
        if (component.getVisibility() != GLView.VISIBLE
+1 −1
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ class PositionController {
        SNAPBACK_ANIMATION_TIME,  // ANIM_KIND_SNAPBACK
        400,  // ANIM_KIND_SLIDE
        300,  // ANIM_KIND_ZOOM
        GLView.ANIM_TIME_OPENING,  // ANIM_KIND_OPENING
        300,  // ANIM_KIND_OPENING
        0,    // ANIM_KIND_FLING (the duration is calculated dynamically)
        0,    // ANIM_KIND_FLING_X (see the comment above)
        0,    // ANIM_KIND_DELETE (the duration is calculated dynamically)
Loading