【发布时间】:2018-05-21 22:21:39
【问题描述】:
我正在尝试将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 中,从而导致应用程序崩溃抛出上述错误。
由于这是在 RecyclerView 内部引起的问题,因此如果其中没有动画,我会非常好,因此我想知道如何在 TransitionManager.beginDelayedTransition 中指定仅动画直接子视图ConstraintLayout,这样它就不会为 RecyclerView 内的视图设置动画。
相关文档对此没有任何帮助,所以我在这里提出这个问题;如何将转换限制为直接子视图?
如果有帮助,我会在此处包含转换管理器的 sn-p
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 -
@pskink
TransitionSet有一种方法可以忽略子视图,谢谢。您可以发布答案以便我接受吗? -
Transition有这样的方法:Transition#excludeTarget/Transition#excludeChildren/Transition#removeTarget -
@pskink 我知道,多亏了您的评论才找到它,这就是为什么我要求您将其发布为我接受它的答案,因为不允许接受 cmets答案。
标签: android android-recyclerview android-transitions