LayoutTransition.DISAPPEARING 移除子视图时动画不会 运行

LayoutTransition.DISAPPEARING animations don't run when removing child views

我有一个 FrameLayout 容器,我试图让它的变化动画化。我在视图上调用 container.setLayoutTransition(layoutTransition),但是当我稍后调用 container.removeView(v) 时,DISAPPEARING 动画没有执行,视图被立即删除。

这是我的转换代码:

LayoutTransition layoutTransition = new LayoutTransition();
layoutTransition.setAnimator(LayoutTransition.APPEARING,
    ObjectAnimator.ofFloat(null, View.TRANSLATION_Y, toolHeight, 0f));
layoutTransition.setStartDelay(LayoutTransition.APPEARING, 0);
layoutTransition.setDuration(LayoutTransition.APPEARING, 1000);
layoutTransition.setAnimator(LayoutTransition.DISAPPEARING,
    ObjectAnimator.ofFloat(null, View.TRANSLATION_Y, 0f, toolHeight));
layoutTransition.setStartDelay(LayoutTransition.DISAPPEARING, 0);
layoutTransition.setDuration(LayoutTransition.DISAPPEARING, 1000);
container.setLayoutTransition(layoutTransition);

为了交换观点,我这样做了:

if (container.getChildCount() > 0) {
  for (int i = container.getChildCount() - 1; i >= 0; i--) {
    container.removeViewAt(i);
  }
}
container.addView(newView);

我放慢了动画以确认情况,我可以清楚地看到 APPEARING 过渡执行得当,但 DISAPPEARING 过渡不是,视图很简单立即删除。

我发现,如果我从 LayoutTransition.removeChild() 方法中删除视图,它会起作用,但这会增加很多似乎没有必要的复杂性。这就是它的样子:

if (container.getChildCount() > 0) {
  final View v = container.getChildAt(0);
  container.getLayoutTransition().removeChild(container, v);
  container.getLayoutTransition().addTransitionListener(new LayoutTransition.TransitionListener() {
    @Override
    public void startTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
    }

    @Override
    public void endTransition(LayoutTransition transition, ViewGroup container, View view, int transitionType) {
      transition.removeTransitionListener(this);
      if (transitionType == LayoutTransition.DISAPPEARING) {
        container.removeView(view);
      }
    }
  }
}
container.addView(newView);

觉得这很糟糕?这只是为了一次删除一个视图,如果容器中有多个视图,那么我必须添加一个转换监听器来计算执行次数以知道何时删除自己,这只是一团糟。

删除本身很有趣,因为如果我只是将那个转换侦听器放在 LayoutTransition 上并且它不会自行删除,那么消失的转换不会再次 运行。

很明显,我遗漏了与执行删除转换有关的内容。任何帮助将不胜感激。

编辑

有人向我指出添加视图会取消 DISAPPEARING 转换:

public class ViewGroup {
  private void addViewInner(...) {
    if (mTransition != null) {
      // Don't prevent other add transitions from completing, but cancel remove
      // transitions to let them complete the process before we add to the container
      mTransition.cancel(LayoutTransition.DISAPPEARING);
    }
  }
}

这对我来说意义不大。想知道这里的推理是什么。

正如您所注意到的,LayoutTransition 并不像某些较新的 API 那样真正对动画类型进行排序。它旨在一次处理单个项目更改。最干净的代码将来自延迟添加自己的顺序,而不是链接侦听器调用:

if (container.getChildCount() > 0) {
  for (int i = container.getChildCount() - 1; i >= 0; i--) {
    container.removeViewAt(i);
  }

  //Start the add once removals are complete
  long duration =
    container.getLayoutTransition().getDuration(LayoutTransition.DISAPPEARING);
  container.postOnAnimationDelayed(new Runnable(){
    @Override
    public void run() {
      container.addView(newView);
    }
  }, duration);
} else {
  container.addView(newView);
}

对于这样的事情,您可能会从 Scenes 中获得更好的编排,但那是 API 19+