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

Commit b9044372 authored by Abodunrinwa Toki's avatar Abodunrinwa Toki
Browse files

Fix FloatingToolbar animation interruptions.

This CL makes sure animations don't conflict with one another.
Cancelling an animation should also set the animating object to
the end state.

Change-Id: Ib74515bb99090ce11a6ccd840aba0baee9fc1bf5
parent 7270d07a
Loading
Loading
Loading
Loading
+116 −59
Original line number Diff line number Diff line
@@ -288,13 +288,8 @@ public final class FloatingToolbar {

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        // This animation should never be run if the overflow panel has not been
                        // initialized.
                        Preconditions.checkNotNull(mOverflowPanel);
                        mContentContainer.removeAllViews();
                        mContentContainer.addView(mOverflowPanel.getView());
                        setOverflowPanelAsContent();
                        mOverflowPanel.fadeIn(true);
                        setContentAreaAsTouchableSurface();
                    }

                    @Override
@@ -307,13 +302,8 @@ public final class FloatingToolbar {

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        // This animation should never be run if the main panel has not been
                        // initialized.
                        Preconditions.checkNotNull(mMainPanel);
                        mContentContainer.removeAllViews();
                        mContentContainer.addView(mMainPanel.getView());
                        setMainPanelAsContent();
                        mMainPanel.fadeIn(true);
                        setContentAreaAsTouchableSurface();
                    }

                    @Override
@@ -323,6 +313,24 @@ public final class FloatingToolbar {
        private final AnimatorSet mShowAnimation;
        private final AnimatorSet mDismissAnimation;
        private final AnimatorSet mHideAnimation;
        private final AnimationSet mOpenOverflowAnimation = new AnimationSet(true) {
            @Override
            public void cancel() {
                if (hasStarted() && !hasEnded()) {
                    super.cancel();
                    setOverflowPanelAsContent();
                }
            }
        };
        private final AnimationSet mCloseOverflowAnimation = new AnimationSet(true) {
            @Override
            public void cancel() {
                if (hasStarted() && !hasEnded()) {
                    super.cancel();
                    setMainPanelAsContent();
                }
            }
        };

        private final Runnable mOpenOverflow = new Runnable() {
            @Override
@@ -363,7 +371,7 @@ public final class FloatingToolbar {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            mPopupWindow.dismiss();
                            setMainPanelAsContent();
                            mContentContainer.removeAllViews();
                        }
                    });
            mHideAnimation = createShrinkFadeOutFromBottomAnimation(
@@ -429,8 +437,15 @@ public final class FloatingToolbar {

            mHidden = false;
            mDismissed = false;
            stopDismissAndHideAnimations();
            cancelAllAnimations();
            // Make sure a panel is set as the content.
            if (mContentContainer.getChildCount() == 0) {
                setMainPanelAsContent();
            }
            preparePopupContent();
            // If we're yet to show the popup, set the container visibility to zero.
            // The "show" animation will make this visible.
            mContentContainer.setAlpha(0);
            mPopupWindow.showAtLocation(mParent, Gravity.NO_GRAVITY, x, y);
            runShowAnimation();
        }
@@ -487,6 +502,7 @@ public final class FloatingToolbar {
                return;
            }

            cancelAllAnimations();
            preparePopupContent();
            mPopupWindow.update(x, y, getWidth(), getHeight());
        }
@@ -550,21 +566,24 @@ public final class FloatingToolbar {
            mHideAnimation.start();
        }

        private void stopDismissAndHideAnimations() {
        private void cancelAllAnimations() {
            mShowAnimation.cancel();
            mDismissAnimation.cancel();
            mHideAnimation.cancel();
            mOpenOverflowAnimation.cancel();
            mCloseOverflowAnimation.cancel();
        }

        /**
         * Opens the floating toolbar overflow.
         * This method should not be called if menu items have not been laid out with
         * {@link #layoutMenuItems(List, MenuItem.OnMenuItemClickListener, int)}.
         * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}.
         *
         * @throws IllegalStateException if called when menu items have not been laid out.
         */
        private void openOverflow() {
            Preconditions.checkNotNull(mMainPanel);
            Preconditions.checkNotNull(mOverflowPanel);
            Preconditions.checkState(mMainPanel != null);
            Preconditions.checkState(mOverflowPanel != null);

            mMainPanel.fadeOut(true);
            Size overflowPanelSize = mOverflowPanel.measure();
@@ -601,11 +620,11 @@ public final class FloatingToolbar {
            widthAnimation.setDuration(240);
            heightAnimation.setDuration(180);
            heightAnimation.setStartOffset(60);
            AnimationSet animation = new AnimationSet(true);
            animation.setAnimationListener(mOnOverflowOpened);
            animation.addAnimation(widthAnimation);
            animation.addAnimation(heightAnimation);
            mContentContainer.startAnimation(animation);
            mOpenOverflowAnimation.getAnimations().clear();
            mOpenOverflowAnimation.setAnimationListener(mOnOverflowOpened);
            mOpenOverflowAnimation.addAnimation(widthAnimation);
            mOpenOverflowAnimation.addAnimation(heightAnimation);
            mContentContainer.startAnimation(mOpenOverflowAnimation);
        }

        /**
@@ -613,11 +632,11 @@ public final class FloatingToolbar {
         * This method should not be called if menu items have not been laid out with
         * {@link #layoutMenuItems(java.util.List, MenuItem.OnMenuItemClickListener, int)}.
         *
         * @throws IllegalStateException
         * @throws IllegalStateException if called when menu items have not been laid out.
         */
        private void closeOverflow() {
            Preconditions.checkNotNull(mMainPanel);
            Preconditions.checkNotNull(mOverflowPanel);
            Preconditions.checkState(mMainPanel != null);
            Preconditions.checkState(mOverflowPanel != null);

            mOverflowPanel.fadeOut(true);
            Size mainPanelSize = mMainPanel.measure();
@@ -653,39 +672,73 @@ public final class FloatingToolbar {
            widthAnimation.setDuration(150);
            widthAnimation.setStartOffset(150);
            heightAnimation.setDuration(210);
            AnimationSet animation = new AnimationSet(true);
            animation.setAnimationListener(mOnOverflowClosed);
            animation.addAnimation(widthAnimation);
            animation.addAnimation(heightAnimation);
            mContentContainer.startAnimation(animation);
            mCloseOverflowAnimation.getAnimations().clear();
            mCloseOverflowAnimation.setAnimationListener(mOnOverflowClosed);
            mCloseOverflowAnimation.addAnimation(widthAnimation);
            mCloseOverflowAnimation.addAnimation(heightAnimation);
            mContentContainer.startAnimation(mCloseOverflowAnimation);
        }

        /**
         * Prepares the content container for show and update calls.
         */
        private void preparePopupContent() {
            // Do not call this method if main view panel has not been initialized.
            Preconditions.checkNotNull(mMainPanel);

            // If we're yet to show the popup, set the container visibility to zero.
            // The "show" animation will make this visible.
            if (!mPopupWindow.isShowing()) {
                mContentContainer.setAlpha(0);
            }

            // Make sure panels are visible.
            // Reset visibility.
            if (mMainPanel != null) {
                mMainPanel.fadeIn(false);
            }
            if (mOverflowPanel != null) {
                mOverflowPanel.fadeIn(false);
            }

            // Make sure a panel is set as the content.
            if (mContentContainer.getChildCount() == 0) {
            // Reset position.
            if (mMainPanel != null
                    && mContentContainer.getChildAt(0) == mMainPanel.getView()) {
                positionMainPanel();
            }
            if (mOverflowPanel != null
                    && mContentContainer.getChildAt(0) == mOverflowPanel.getView()) {
                positionOverflowPanel();
            }
        }

        /**
         * Sets the current content to be the main view panel.
         */
        private void setMainPanelAsContent() {
            // This should never be called if the main panel has not been initialized.
            Preconditions.checkNotNull(mMainPanel);
            mContentContainer.removeAllViews();
            Size mainPanelSize = mMainPanel.measure();
            ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
            params.width = mainPanelSize.getWidth();
            params.height = mainPanelSize.getHeight();
            mContentContainer.setLayoutParams(params);
            mContentContainer.addView(mMainPanel.getView());
            setContentAreaAsTouchableSurface();
        }

        /**
         * Sets the current content to be the overflow view panel.
         */
        private void setOverflowPanelAsContent() {
            // This should never be called if the overflow panel has not been initialized.
            Preconditions.checkNotNull(mOverflowPanel);
            mContentContainer.removeAllViews();
            Size overflowPanelSize = mOverflowPanel.measure();
            ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
            params.width = overflowPanelSize.getWidth();
            params.height = overflowPanelSize.getHeight();
            mContentContainer.setLayoutParams(params);
            mContentContainer.addView(mOverflowPanel.getView());
            setContentAreaAsTouchableSurface();
        }

            // Make sure the main panel is at the correct position.
            if (mContentContainer.getChildAt(0) == mMainPanel.getView()) {
        /**
         * Places the main view panel at the appropriate resting coordinates.
         */
        private void positionMainPanel() {
            Preconditions.checkNotNull(mMainPanel);
            float x = mPopupWindow.getWidth()
                    - (mMainPanel.getView().getMeasuredWidth() + mMarginHorizontal);
            mContentContainer.setX(x);
@@ -696,22 +749,19 @@ public final class FloatingToolbar {
                        - (mMainPanel.getView().getMeasuredHeight() + mMarginVertical);
            }
            mContentContainer.setY(y);
            }

            setContentAreaAsTouchableSurface();
        }

        /**
         * Sets the current content to be the main view panel.
         * Places the main view panel at the appropriate resting coordinates.
         */
        private void setMainPanelAsContent() {
            mContentContainer.removeAllViews();
            Size mainPanelSize = mMainPanel.measure();
            ViewGroup.LayoutParams params = mContentContainer.getLayoutParams();
            params.width = mainPanelSize.getWidth();
            params.height = mainPanelSize.getHeight();
            mContentContainer.setLayoutParams(params);
            mContentContainer.addView(mMainPanel.getView());
        private void positionOverflowPanel() {
            Preconditions.checkNotNull(mOverflowPanel);
            float x = mPopupWindow.getWidth()
                    - (mOverflowPanel.getView().getMeasuredWidth() + mMarginHorizontal);
            mContentContainer.setX(x);
            mContentContainer.setY(mMarginVertical);
            setContentAreaAsTouchableSurface();
        }

        private void updatePopupSize() {
@@ -1080,6 +1130,7 @@ public final class FloatingToolbar {
        }

        public void fadeIn(boolean animate) {
            cancelFadeAnimations();
            if (animate) {
                mFadeInAnimation.start();
            } else {
@@ -1088,12 +1139,18 @@ public final class FloatingToolbar {
        }

        public void fadeOut(boolean animate) {
            cancelFadeAnimations();
            if (animate) {
                mFadeOutAnimation.start();
            } else {
                mView.setAlpha(0);
            }
        }

        private void cancelFadeAnimations() {
            mFadeInAnimation.cancel();
            mFadeOutAnimation.cancel();
        }
    }