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

Commit a035b562 authored by George Mount's avatar George Mount Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE Allow enter activity transitions to be delayed until data...

Merge "DO NOT MERGE Allow enter activity transitions to be delayed until data is ready." into lmp-preview-dev
parents bbd2909d 28a8d108
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3335,6 +3335,7 @@ package android.app {
    method public void openContextMenu(android.view.View);
    method public void openOptionsMenu();
    method public void overridePendingTransition(int, int);
    method public void postponeEnterTransition();
    method public void recreate();
    method public void registerForContextMenu(android.view.View);
    method public final deprecated void removeDialog(int);
@@ -3390,6 +3391,7 @@ package android.app {
    method public deprecated void startManagingCursor(android.database.Cursor);
    method public boolean startNextMatchingActivity(android.content.Intent);
    method public boolean startNextMatchingActivity(android.content.Intent, android.os.Bundle);
    method public void startPostponedEnterTransition();
    method public void startSearch(java.lang.String, boolean, android.os.Bundle, boolean);
    method public void stopLockTask();
    method public deprecated void stopManagingCursor(android.database.Cursor);
+28 −0
Original line number Diff line number Diff line
@@ -5616,6 +5616,34 @@ public class Activity extends ContextThemeWrapper
        mExitTransitionListener = listener;
    }

    /**
     * Postpone the entering activity transition when Activity was started with
     * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
     * android.util.Pair[])}.
     * <p>This method gives the Activity the ability to delay starting the entering and
     * shared element transitions until all data is loaded. Until then, the Activity won't
     * draw into its window, leaving the window transparent. This may also cause the
     * returning animation to be delayed until data is ready. This method should be
     * called in {@link #onCreate(android.os.Bundle)} or in
     * {@link #onActivityReenter(int, android.content.Intent)}.
     * {@link #startPostponedEnterTransition()} must be called to allow the Activity to
     * start the transitions. If the Activity did not use
     * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(Activity,
     * android.util.Pair[])}, then this method does nothing.</p>
     */
    public void postponeEnterTransition() {
        mActivityTransitionState.postponeEnterTransition();
    }

    /**
     * Begin postponed transitions after {@link #postponeEnterTransition()} was called.
     * If postponeEnterTransition() was called, you must call startPostponedEnterTransition()
     * to have your Activity start drawing.
     */
    public void startPostponedEnterTransition() {
        mActivityTransitionState.startPostponedEnterTransition();
    }

    // ------------------ Internal API ------------------
    
    final void setParent(Activity parent) {
+12 −0
Original line number Diff line number Diff line
@@ -214,11 +214,21 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
            ArrayList<String> allSharedElementNames,
            ArrayList<String> accepted, ArrayList<String> localNames,
            SharedElementListener listener, boolean isReturning) {
        this(window, allSharedElementNames, listener, isReturning);
        viewsReady(accepted, localNames);
    }

    public ActivityTransitionCoordinator(Window window,
            ArrayList<String> allSharedElementNames,
            SharedElementListener listener, boolean isReturning) {
        super(new Handler());
        mWindow = window;
        mListener = listener;
        mAllSharedElementNames = allSharedElementNames;
        mIsReturning = isReturning;
    }

    protected void viewsReady(ArrayList<String> accepted, ArrayList<String> localNames) {
        setSharedElements(accepted, localNames);
        if (getViewsTransition() != null) {
            getDecor().captureTransitioningViews(mTransitioningViews);
@@ -274,6 +284,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
        return names;
    }

    public ArrayList<String> getAllSharedElementNames() { return mAllSharedElementNames; }

    public static void setViewVisibility(Collection<View> views, int visibility) {
        if (views != null) {
            for (View view : views) {
+33 −5
Original line number Diff line number Diff line
@@ -87,6 +87,11 @@ class ActivityTransitionState {
     */
    private boolean mHasExited;

    /**
     * Postpone painting and starting the enter transition until this is false.
     */
    private boolean mIsEnterPostponed;

    public ActivityTransitionState() {
    }

@@ -140,15 +145,38 @@ class ActivityTransitionState {
        if (mEnterActivityOptions.isReturning()) {
            restoreExitedViews();
            activity.getWindow().getDecorView().setVisibility(View.VISIBLE);
        }
        mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity,
                    resultReceiver, sharedElementNames, mExitingFrom, mExitingTo);
                resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning());

        if (!mIsEnterPostponed) {
            startEnter();
        }
    }

    public void postponeEnterTransition() {
        mIsEnterPostponed = true;
    }

    public void startPostponedEnterTransition() {
        if (mIsEnterPostponed) {
            mIsEnterPostponed = false;
            if (mEnterTransitionCoordinator != null) {
                startEnter();
            }
        }
    }

    private void startEnter() {
        if (mEnterActivityOptions.isReturning()) {
            mEnterTransitionCoordinator.viewsReady(mExitingFrom, mExitingTo);
        } else {
            mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity,
                    resultReceiver, sharedElementNames, null, null);
            mEnteringNames = sharedElementNames;
            mEnterTransitionCoordinator.viewsReady(null, null);
            mEnteringNames = mEnterTransitionCoordinator.getAllSharedElementNames();
            mEnteringFrom = mEnterTransitionCoordinator.getAcceptedNames();
            mEnteringTo = mEnterTransitionCoordinator.getMappedNames();
        }

        mExitingFrom = null;
        mExitingTo = null;
        mEnterActivityOptions = null;
+55 −16
Original line number Diff line number Diff line
@@ -53,18 +53,37 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
    private boolean mIsCanceled;
    private ObjectAnimator mBackgroundAnimator;
    private boolean mIsExitTransitionComplete;
    private boolean mIsReadyForTransition;
    private Bundle mSharedElementsBundle;

    public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver,
            ArrayList<String> sharedElementNames,
            ArrayList<String> acceptedNames, ArrayList<String> mappedNames) {
        super(activity.getWindow(), sharedElementNames, acceptedNames, mappedNames,
                getListener(activity, acceptedNames), acceptedNames != null);
            ArrayList<String> sharedElementNames, boolean isReturning) {
        super(activity.getWindow(), sharedElementNames,
                getListener(activity, isReturning), isReturning);
        mActivity = activity;
        setResultReceiver(resultReceiver);
        prepareEnter();
        Bundle resultReceiverBundle = new Bundle();
        resultReceiverBundle.putParcelable(KEY_REMOTE_RECEIVER, this);
        mResultReceiver.send(MSG_SET_REMOTE_RECEIVER, resultReceiverBundle);
        getDecor().getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                if (mIsReadyForTransition) {
                    getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
                }
                return mIsReadyForTransition;
            }
        });
    }

    public void viewsReady(ArrayList<String> accepted, ArrayList<String> localNames) {
        if (mIsReadyForTransition) {
            return;
        }
        super.viewsReady(accepted, localNames);

        mIsReadyForTransition = true;
        if (mIsReturning) {
            mHandler = new Handler() {
                @Override
@@ -75,6 +94,13 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
            mHandler.sendEmptyMessageDelayed(MSG_CANCEL, MAX_WAIT_MS);
            send(MSG_SEND_SHARED_ELEMENT_DESTINATION, null);
        }
        setViewVisibility(mSharedElements, View.INVISIBLE);
        if (getViewsTransition() != null) {
            setViewVisibility(mTransitioningViews, View.INVISIBLE);
        }
        if (mSharedElementsBundle != null) {
            onTakeSharedElements();
        }
    }

    private void sendSharedElementDestination() {
@@ -94,9 +120,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
        }
    }

    private static SharedElementListener getListener(Activity activity,
            ArrayList<String> acceptedNames) {
        boolean isReturning = acceptedNames != null;
    private static SharedElementListener getListener(Activity activity, boolean isReturning) {
        return isReturning ? activity.mExitTransitionListener : activity.mEnterTransitionListener;
    }

@@ -108,7 +132,8 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
                    if (mHandler != null) {
                        mHandler.removeMessages(MSG_CANCEL);
                    }
                    onTakeSharedElements(resultData);
                    mSharedElementsBundle = resultData;
                    onTakeSharedElements();
                }
                break;
            case MSG_EXIT_TRANSITION_COMPLETE:
@@ -139,7 +164,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
            mSharedElementNames.clear();
            mSharedElements.clear();
            mAllSharedElementNames.clear();
            onTakeSharedElements(null);
            startSharedElementTransition(null);
            onRemoteExitTransitionComplete();
        }
    }
@@ -149,10 +174,6 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
    }

    protected void prepareEnter() {
        setViewVisibility(mSharedElements, View.INVISIBLE);
        if (getViewsTransition() != null) {
            setViewVisibility(mTransitioningViews, View.INVISIBLE);
        }
        mActivity.overridePendingTransition(0, 0);
        if (!mIsReturning) {
            mActivity.convertToTranslucent(null, null);
@@ -185,7 +206,25 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
        }
    }

    protected void onTakeSharedElements(Bundle sharedElementState) {
    protected void onTakeSharedElements() {
        if (!mIsReadyForTransition || mSharedElementsBundle == null) {
            return;
        }
        final Bundle sharedElementState = mSharedElementsBundle;
        mSharedElementsBundle = null;
        getDecor().getViewTreeObserver()
                .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                    @Override
                    public boolean onPreDraw() {
                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
                        startSharedElementTransition(sharedElementState);
                        return false;
                    }
                });
        getDecor().invalidate();
    }

    private void startSharedElementTransition(Bundle sharedElementState) {
        setEpicenter();
        // Remove rejected shared elements
        ArrayList<String> rejectedNames = new ArrayList<String>(mAllSharedElementNames);
@@ -299,8 +338,8 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
    }

    public void stop() {
        makeOpaque();
        mHasStopped = true;
        mActivity = null;
        mIsCanceled = true;
        mResultReceiver = null;
        if (mBackgroundAnimator != null) {
@@ -310,7 +349,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
    }

    private void makeOpaque() {
        if (!mHasStopped) {
        if (!mHasStopped && mActivity != null) {
            mActivity.convertFromTranslucent();
            mActivity = null;
        }