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

Commit e025ed2f authored by Alan Viverette's avatar Alan Viverette
Browse files

Make popup transition animation play nicely with dismiss/show pair

Previously it was okay to call dismiss/show in quick succession since
the window was removed synchronously. Adding transitions introduced a
delay between dismiss() and actually removing the window, which broke
this behavior.

Change-Id: I0de8ae0a551dcb2eb8b8a50356c308b654ebdc6f
parent 84183103
Loading
Loading
Loading
Loading
+26 −1
Original line number Diff line number Diff line
@@ -268,7 +268,12 @@ public class TransitionManager {
        @Override
        public boolean onPreDraw() {
            removeListeners();
            sPendingTransitions.remove(mSceneRoot);

            // Don't start the transition if it's no longer pending.
            if (!sPendingTransitions.remove(mSceneRoot)) {
                return true;
            }

            // Add to running list, handle end to remove it
            final ArrayMap<ViewGroup, ArrayList<Transition>> runningTransitions =
                    getRunningTransitions();
@@ -417,4 +422,24 @@ public class TransitionManager {
            sceneChangeRunTransition(sceneRoot, transitionClone);
        }
    }

    /**
     * Ends all pending and ongoing transitions on the specified scene root.
     *
     * @param sceneRoot The root of the View hierarchy to end transitions on.
     * @hide
     */
    public static void endTransitions(final ViewGroup sceneRoot) {
        sPendingTransitions.remove(sceneRoot);

        final ArrayList<Transition> runningTransitions = getRunningTransitions().get(sceneRoot);
        if (runningTransitions != null) {
            final int count = runningTransitions.size();
            for (int i = 0; i < count; i++) {
                final Transition transition = runningTransitions.get(i);
                transition.end();
            }
        }

    }
}
+71 −59
Original line number Diff line number Diff line
@@ -1020,23 +1020,24 @@ public class PopupWindow {
            return;
        }

        TransitionManager.endTransitions(mDecorView);

        unregisterForScrollChanged();

        mIsShowing = true;
        mIsDropdown = false;

        WindowManager.LayoutParams p = createPopupLayout(token);
        p.windowAnimations = computeAnimationResource();

        final WindowManager.LayoutParams p = createPopupLayoutParams(token);
        preparePopup(p);
        if (gravity == Gravity.NO_GRAVITY) {
            gravity = Gravity.TOP | Gravity.START;
        }

        // Only override the default if some gravity was specified.
        if (gravity != Gravity.NO_GRAVITY) {
            p.gravity = gravity;
        }

        p.x = x;
        p.y = y;
        if (mHeightMode < 0) p.height = mLastHeight = mHeightMode;
        if (mWidthMode < 0) p.width = mLastWidth = mWidthMode;

        invokePopup(p);
    }

@@ -1102,20 +1103,18 @@ public class PopupWindow {
            return;
        }

        TransitionManager.endTransitions(mDecorView);

        registerForScrollChanged(anchor, xoff, yoff, gravity);

        mIsShowing = true;
        mIsDropdown = true;

        WindowManager.LayoutParams p = createPopupLayout(anchor.getWindowToken());
        final WindowManager.LayoutParams p = createPopupLayoutParams(anchor.getWindowToken());
        preparePopup(p);

        updateAboveAnchor(findDropDownPosition(anchor, p, xoff, yoff, gravity));

        if (mHeightMode < 0) p.height = mLastHeight = mHeightMode;
        if (mWidthMode < 0) p.width = mLastWidth = mWidthMode;

        p.windowAnimations = computeAnimationResource();
        final boolean aboveAnchor = findDropDownPosition(anchor, p, xoff, yoff, gravity);
        updateAboveAnchor(aboveAnchor);

        invokePopup(p);
    }
@@ -1157,10 +1156,9 @@ public class PopupWindow {
    }

    /**
     * <p>Prepare the popup by embedding in into a new ViewGroup if the
     * background drawable is not null. If embedding is required, the layout
     * parameters' height is modified to take into account the background's
     * padding.</p>
     * Prepare the popup by embedding it into a new ViewGroup if the background
     * drawable is not null. If embedding is required, the layout parameters'
     * height is modified to take into account the background's padding.
     *
     * @param p the layout parameters of the popup's content view
     */
@@ -1293,26 +1291,39 @@ public class PopupWindow {
     *
     * @return the layout parameters to pass to the window manager
     */
    private WindowManager.LayoutParams createPopupLayout(IBinder token) {
        // generates the layout parameters for the drop down
        // we want a fixed size view located at the bottom left of the anchor
        WindowManager.LayoutParams p = new WindowManager.LayoutParams();
        // these gravity settings put the view at the top left corner of the
        // screen. The view is then positioned to the appropriate location
        // by setting the x and y offsets to match the anchor's bottom
        // left corner
    private WindowManager.LayoutParams createPopupLayoutParams(IBinder token) {
        final WindowManager.LayoutParams p = new WindowManager.LayoutParams();

        // These gravity settings put the view at the top left corner of the
        // screen. The view is then positioned to the appropriate location by
        // setting the x and y offsets to match the anchor's bottom-left
        // corner.
        p.gravity = Gravity.START | Gravity.TOP;
        p.width = mLastWidth = mWidth;
        p.height = mLastHeight = mHeight;
        p.flags = computeFlags(p.flags);
        p.type = mWindowLayoutType;
        p.token = token;
        p.softInputMode = mSoftInputMode;
        p.windowAnimations = computeAnimationResource();

        if (mBackground != null) {
            p.format = mBackground.getOpacity();
        } else {
            p.format = PixelFormat.TRANSLUCENT;
        }
        p.flags = computeFlags(p.flags);
        p.type = mWindowLayoutType;
        p.token = token;
        p.softInputMode = mSoftInputMode;

        if (mHeightMode < 0) {
            p.height = mLastHeight = mHeightMode;
        } else {
            p.height = mLastHeight = mHeight;
        }

        if (mWidthMode < 0) {
            p.width = mLastWidth = mWidthMode;
        } else {
            p.width = mLastWidth = mWidth;
        }

        // Used for debugging.
        p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));

        return p;
@@ -1569,11 +1580,14 @@ public class PopupWindow {
     * @see #showAsDropDown(android.view.View)
     */
    public void dismiss() {
        if (isShowing() && mDecorView != null) {
            mIsShowing = false;
        if (!isShowing()) {
            return;
        }

        unregisterForScrollChanged();

        mIsShowing = false;

        if (mExitTransition != null) {
            mExitTransition.addTarget(mBackgroundView);
            mExitTransition.addListener(new Transition.TransitionListenerAdapter() {
@@ -1594,7 +1608,6 @@ public class PopupWindow {
            dismissImmediate();
        }
    }
    }

    /**
     * Removes the popup from the window manager and tears down the supporting
@@ -1851,15 +1864,13 @@ public class PopupWindow {
    }

    private void unregisterForScrollChanged() {
        WeakReference<View> anchorRef = mAnchor;
        View anchor = null;
        if (anchorRef != null) {
            anchor = anchorRef.get();
        }
        final WeakReference<View> anchorRef = mAnchor;
        final View anchor = anchorRef == null ? null : anchorRef.get();
        if (anchor != null) {
            ViewTreeObserver vto = anchor.getViewTreeObserver();
            final ViewTreeObserver vto = anchor.getViewTreeObserver();
            vto.removeOnScrollChangedListener(mOnScrollChangedListener);
        }

        mAnchor = null;
    }

@@ -1867,7 +1878,8 @@ public class PopupWindow {
        unregisterForScrollChanged();

        mAnchor = new WeakReference<>(anchor);
        ViewTreeObserver vto = anchor.getViewTreeObserver();

        final ViewTreeObserver vto = anchor.getViewTreeObserver();
        if (vto != null) {
            vto.addOnScrollChangedListener(mOnScrollChangedListener);
        }