我试图将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 中删除的淡出视图,从而导致应用程序崩溃并抛出上面的错误。
由于这是在 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);
TransitionManager.beginDelayedTransition
的两个参数版本,传递一个排除了一些视图的Transition
。 - pskinkTransition
has that methods:Transition#excludeTarget
/Transition#excludeChildren
/Transition#removeTarget
- pskink