【问题标题】:Call setVisibility while the view is animated在视图动画时调用 setVisibility
【发布时间】:2017-04-14 22:19:20
【问题描述】:

当我在视图的子视图上调用 setVisibility 而(父)视图使用 ViewCompat.postOnAnimation 进行动画处理时,事情会被破坏。 (setVisibility 不起作用 + 其他一些东西被破坏了)。

问题 - 是否有任何动画方法或解决方法允许在父动画时对子调用 setVisibility?

这是一个非常重要的请求,我认为这并不罕见,因为例如 http 请求是在随机时间返回的,并且在此期间可以随时为视图设置动画。

代码请求编辑:

关于代码,有点复杂。我先解释一下。它是自定义 CoordinatorLayout Behavior 中的动画,是标准 BottomSheetBehavior 的克隆(工作表从下向上滑动)。

通过调用这个来启动动画:

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

SettleRunnable 是这样的:

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);
        }
    }
}

如你所见,所有的动画移动都是由 mViewDragHelper.continueSettling 完成的。拖动助手是标准类 ViewDragHelper。

ViewDragHelper.continueSettling 看起来像这样

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;
}

它只是根据所选的目标状态将工作表向上或向下移动到所需位置。

问题的伪代码是:

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

我可以等到动画结束,但正如我所说,如果 http 请求有点问题,我希望立即刷新数据而无需等待。

  • 动画元素是 CoordinatorLayout。受 setVisibility 影响的孩子是其一个或多个孩子。

  • this link 来看,android 似乎在动画和 setVisibility 方面普遍存在问题。

我现在想到的可能解决方案:

  • 也许我会用另一个并行的 postOnAnimation() 任务来改变可见性 (?)

  • 或者因为它基本上只是一步一步地后续调用移动函数mViewDragHelper.continueSettling(),为什么不用postOnAnimation()不做呢?没有它我也可以运行任务。但我猜 postOnAnimation 为具体设备选择了一些正确的动画步骤延迟 + 可能还有其他一些东西。

【问题讨论】:

  • 可以分享代码吗?
  • 嗨,我编辑了代码

标签: android animation view


【解决方案1】:

您可以将AnimatorListenerAdapter 添加到您的父动画中,并覆盖onAnimationEnd() 方法。在此方法中,您可以调用子动画。但是,我宁愿改变视图的 alpha 而不是可见性。在这种情况下,您可以实现更流畅的效果。

例如,考虑以下代码:

 parentAnimationInstance.addListener(new AnimatorListenerAdapter() {
                                            @Override
                                            public void onAnimationEnd(Animator animation) {
                                                super.onAnimationEnd(animation);
                                                childView.animate()
                                                    .alpha(1.f)
                                                    .setDuration(200)
                                                    .start();
                                            }
                                        });

【讨论】:

  • 嗨。是的,等到动画结束是解决方案之一。我想知道在视图动画时是否可以使用孩子的可见性,但是谢谢。
  • 可以达到同样的效果。这要容易得多。
猜你喜欢
  • 2012-01-31
  • 2023-03-28
  • 1970-01-01
  • 2012-10-21
  • 2020-08-26
  • 1970-01-01
  • 2017-05-19
  • 2021-06-20
  • 1970-01-01
相关资源
最近更新 更多