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

Commit 054c172e authored by Alan Viverette's avatar Alan Viverette
Browse files

Show popup transitions when there is no anchor set

Allow anchorRoot to be null when starting exit transition. Pushes
epicenter callback creation into startExitTransition. Adds nullability
annotations.

Bug: 33035511
Test: PopupWindowTest#testEnterExitTransition
Change-Id: Ie752a0d6b29d5eb11c160771d8a78fa6234de5bb
parent 56cbe002
Loading
Loading
Loading
Loading
+25 −17
Original line number Diff line number Diff line
@@ -1835,7 +1835,8 @@ public class PopupWindow {
        // can expect the OnAttachStateChangeListener to have been called prior
        // to executing this method, so we can rely on that instead.
        final Transition exitTransition = mExitTransition;
        if (mIsAnchorRootAttached && exitTransition != null && decorView.isLaidOut()) {
        if (exitTransition != null && decorView.isLaidOut()
                && (mIsAnchorRootAttached || mAnchorRoot == null)) {
            // The decor view is non-interactive and non-IME-focusable during exit transitions.
            final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
            p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -1843,18 +1844,13 @@ public class PopupWindow {
            p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
            mWindowManager.updateViewLayout(decorView, p);

            final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
            final Rect epicenter = getTransitionEpicenter();

            // Once we start dismissing the decor view, all state (including
            // the anchor root) needs to be moved to the decor view since we
            // may open another popup while it's busy exiting.
            final View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
            final Rect epicenter = getTransitionEpicenter();
            exitTransition.setEpicenterCallback(new EpicenterCallback() {
                @Override
                public Rect onGetEpicenter(Transition transition) {
                    return epicenter;
                }
            });
            decorView.startExitTransition(exitTransition, anchorRoot,
            decorView.startExitTransition(exitTransition, anchorRoot, epicenter,
                    new TransitionListenerAdapter() {
                        @Override
                        public void onTransitionEnd(Transition transition) {
@@ -2349,8 +2345,9 @@ public class PopupWindow {
         * its {@code onTransitionEnd} method called even if the transition
         * never starts; however, it may be called with a {@code null} argument.
         */
        public void startExitTransition(Transition transition, final View anchorRoot,
                final TransitionListener listener) {
        public void startExitTransition(@NonNull Transition transition,
                @Nullable final View anchorRoot, @Nullable final Rect epicenter,
                @NonNull final TransitionListener listener) {
            if (transition == null) {
                return;
            }
@@ -2358,24 +2355,35 @@ public class PopupWindow {
            // The anchor view's window may go away while we're executing our
            // transition, in which case we need to end the transition
            // immediately and execute the listener to remove the popup.
            if (anchorRoot != null) {
                anchorRoot.addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
            }

            // The exit listener MUST be called for cleanup, even if the
            // transition never starts or ends. Stash it for later.
            mPendingExitListener = new TransitionListenerAdapter() {
                @Override
                public void onTransitionEnd(Transition transition) {
                public void onTransitionEnd(Transition t) {
                    if (anchorRoot != null) {
                        anchorRoot.removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
                    listener.onTransitionEnd(transition);
                    }

                    listener.onTransitionEnd(t);

                    // The listener was called. Our job here is done.
                    mPendingExitListener = null;
                    transition.removeListener(this);
                    t.removeListener(this);
                }
            };

            final Transition exitTransition = transition.clone();
            exitTransition.addListener(mPendingExitListener);
            exitTransition.setEpicenterCallback(new EpicenterCallback() {
                @Override
                public Rect onGetEpicenter(Transition transition) {
                    return epicenter;
                }
            });

            final int count = getChildCount();
            for (int i = 0; i < count; i++) {