在视图动画时调用 setVisibility
Posted
技术标签:
【中文标题】在视图动画时调用 setVisibility【英文标题】:Call setVisibility while the view is animated 【发布时间】: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 为具体设备选择了一些正确的动画步骤延迟 + 可能还有其他一些东西。
【问题讨论】:
可以分享代码吗? 嗨,我编辑了代码 【参考方案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();
);
【讨论】:
嗨。是的,等到动画结束是解决方案之一。我想知道在视图动画时是否可以使用孩子的可见性,但是谢谢。 可以达到同样的效果。这要容易得多。以上是关于在视图动画时调用 setVisibility的主要内容,如果未能解决你的问题,请参考以下文章
仅在用户滚动时调用 Scroll,而不是在 animate()
如何在移动时调整 UIView 的大小,就像 SnapGuide 一样?
暂停时调用 UIViewPropertyAnimator 完成