0

When i call setVisibility on view's child while the (parent) view is animated with ViewCompat.postOnAnimation things get broken. (setVisibility doesn't work + some other things get broken).

Question - is there any method of animation or workaround which allows to call setVisibility on child while the parent is animated?

This is very important request and i think not so unusual, because for example http request is returned in random time, and the view can be animated anytime during that.

Code request edit:

Regarding code, it is bit complicated. I will first explain. It is animation in the custom CoordinatorLayout Behavior, clone of the standard BottomSheetBehavior (sliding of sheet from bottom to up).

Animation is launched by calling this:

ViewCompat.postOnAnimation(child, new SettleRunnable(child, targetState));

SettleRunnable is this:

private class SettleRunnable implements Runnable {

    private final View mView;

    @State
    private final int mTargetState;

    SettleRunnable(View view, @State int targetState) {
        mView = view;
        mTargetState = targetState;
    }

    @Override
    public void run() {
        if (mViewDragHelper != null && mViewDragHelper.continueSettling(true)) {
            ViewCompat.postOnAnimation(mView, this);
        } else {
            setStateInternal(mTargetState);
        }
    }
}

So as you can see, all the animation movement is done by mViewDragHelper.continueSettling. Drag helper is standard class ViewDragHelper.

ViewDragHelper.continueSettling looks like this

public boolean continueSettling(boolean deferCallbacks) {
    if (mDragState == STATE_SETTLING) {
        boolean keepGoing = mScroller.computeScrollOffset();
        final int x = mScroller.getCurrX();
        final int y = mScroller.getCurrY();
        final int dx = x - mCapturedView.getLeft();
        final int dy = y - mCapturedView.getTop();

        if (dx != 0) {
            ViewCompat.offsetLeftAndRight(mCapturedView, dx);
        }
        if (dy != 0) {
            ViewCompat.offsetTopAndBottom(mCapturedView, dy);
        }

        if (dx != 0 || dy != 0) {
            mCallback.onViewPositionChanged(mCapturedView, x, y, dx, dy);
        }

        if (keepGoing && x == mScroller.getFinalX() && y == mScroller.getFinalY()) {
            // Close enough. The interpolator/scroller might think we're still moving
            // but the user sure doesn't.
            mScroller.abortAnimation();
            keepGoing = false;
        }

        if (!keepGoing) {
            if (deferCallbacks) {
                mParentView.post(mSetIdleRunnable);
            } else {
                setDragState(STATE_IDLE);
            }
        }
    }

    return mDragState == STATE_SETTLING;
}

It simply animates the sheet up or down to desired position according the chosen target state.

Pseudo code of problem is:

launchAnimation(); // it takes eg 300 ms
changeVisibilityOfAnimatedViewChildren(); // this is problem

I can wait until the animation finishes, but as i said, in case of http request it is bit problem, i would like to ideally refresh the data right away without waiting.

  • Animated element is CoordinatorLayout. Affected child by setVisibility is one or more its children.

  • Judging by this link, android seems to have generally problem with animations and setVisibility.

Possible solutions i am thinking of now:

  • Maybe if i would change the visibility with another parallel postOnAnimation() task (?)

  • Or because it are basically just step by step subsequent calls of moving function mViewDragHelper.continueSettling() why don't do it without postOnAnimation()? I could run the task also without it. But i guess that postOnAnimation chooses some correct delay of animation step for concrete device + probably some other things.

Community
  • 1
  • 1
luky
  • 2,263
  • 3
  • 22
  • 40

1 Answers1

0

You can add AnimatorListenerAdapter to your parent animation, and override onAnimationEnd() method. In this method you can call the child animation. However, I would rather change alpha of view than visibility. You can achieve more smoothly effect in this case.

For example, consider this code:

 parentAnimationInstance.addListener(new AnimatorListenerAdapter() {
                                            @Override
                                            public void onAnimationEnd(Animator animation) {
                                                super.onAnimationEnd(animation);
                                                childView.animate()
                                                    .alpha(1.f)
                                                    .setDuration(200)
                                                    .start();
                                            }
                                        });
nullbyte
  • 1,178
  • 8
  • 16
  • Hi. Yes wait until the animation finishes is one of the solutions. I was wondering if is it possible work with the children visibility while the view is animated, but thanks. – luky Nov 30 '16 at 16:29
  • You can achieve the same effect. That is just much easier. – nullbyte Nov 30 '16 at 16:31