如何指定TransitionManager.beginDelayedTransition仅影响直接子视图

时间:2018-05-21 22:21:40

标签: android android-recyclerview android-transitions

我正在尝试将ConstraintLayout与使用动画上下滑动的视图结合使用。 这些视图是垂直组织的,顶部有RecyclerView,其下有两个其他视图:

<constraint layout container>
    [                    ]
    [    recycler view   ] 
    [                    ]
    [48dp height 1st view]
    [48dp height 2nd view]
</constraint layout container>

动画非常简单:点击按钮时,第一个视图从容器底部移动到上面可以看到的位置,再次点击时,它向下移动并在第二个视图上保持重叠。发生这种情况时,顶部的RecyclerView会改变高度,因为它被约束到第一个视图,否则会留下一个空的空间。

到目前为止一直很好并且动画效果很好,但是当用户点击按钮太快时会出现问题,导致以下错误:

    java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

在调查发生了什么之后,我发现这个问题是我用TransitionManager动画更改的结果。我发现有趣的是,当点击按钮移动第一个视图(或向下,只是想象相反的步骤)时,经理正在执行以下操作:

  • 淡出RecyclerView中的第一个/最后一个视图(取决于您是否具有反向布局或从结束启用的堆栈)
  • RecyclerView
  • 中删除该视图
  • 降低RecyclerView
  • 的高度
  • 向上移动第一个视图

即使我在所有我可以想象的地方指定RecyclerView不应该为项目更改设置动画,TransitionManager也会覆盖它,这意味着当同一个视图正在显示时会有一个窗口即将从RecyclerView删除的内容可以再次添加到同一个父级,该窗口是管理员淡出视图的时间。

由于淡入淡出动画的速度不是很快,因此用户可以在此期间轻松点击按钮两次,从而导致管理员重新添加已经在RecyclerView中的淡入淡出视图,从而导致崩溃app抛出上述错误。

由于这是RecyclerView内部引起的问题,因此我内心没有任何动画会很完美,因此我想知道如何在TransitionManager.beginDelayedTransition中指定仅动画直接查看ConstraintLayout的子视图,这样就不会为RecyclerView中的视图设置动画。

相关文档对此没有任何启发,所以我在这里提出这个问题;如何限制转换为直接子视图?

如果它可能有用,我在这里包含过渡管理器的片段

    final ConstraintSet constraintSet;
    final ConstraintLayout constraintLayout;

    constraintSet = new ConstraintSet();
    constraintLayout = (ConstraintLayout) viewParent;

    TransitionManager.beginDelayedTransition(constraintLayout);

    constraintSet.clone(constraintLayout);
    constraintSet.connect(startId, startSide, endId, endSide, margin);
    constraintSet.applyTo(constraintLayout);

2 个答案:

答案 0 :(得分:4)

pskink在评论中发布了答案,但在两次要求他发帖作为我接受并且从不这样做的答案之后,我会发布它并将其标记为已回答。

TransitionManager有一个方法excludeChildren,可以完美地满足我的需求。您可以按类类型,特定视图的子项等使用。

编辑:添加请求的示例

    AutoTransition autoTransition = new AutoTransition();
    autoTransition.excludeChildren(R.id.recyclerView, true);
    TransitionManager.beginDelayedTransition(constraintLayout, autoTransition);

constraintLayout作为目标视图的父级,而R.id.recyclerView是我不想要动画的父级的子视图,在这个特定示例中是。您还可以排除特定班级的所有孩子(例如EditText),依此类推。

答案 1 :(得分:1)

我以这种方式解决了这个问题

TransitionManager.beginDelayedTransition(
                        constraintLayout,
                        TransitionSet().apply {
                            ordering = TransitionSet.ORDERING_SEQUENTIAL
                            addTransition(ChangeBounds())
                            addTransition(Fade(Fade.IN))
                        }
                    )

AutoTransition内的代码几乎相同,如果我们不通过自定义转换,则这是默认代码,但我删除了似乎是导致崩溃的addTransition(Fade(Fade.OUT))。至少对于我来说,动画看起来与原始动画非常相似。