如何指定 TransitionManager.beginDelayedTransition 只影响直接子视图
How to specify TransitionManager.beginDelayedTransition to affect only direct child views
我正在尝试将 ConstraintLayout
与随动画上下滑动的视图结合使用。
这些视图是垂直组织的,顶部有一个 RecyclerView
,下面堆叠了另外两个视图:
<constraint layout container>
[ ]
[ recycler view ]
[ ]
[48dp height 1st view]
[48dp height 2nd view]
</constraint layout container>
动画非常简单:点击按钮时,第一个视图从容器底部移动到您可以在上方看到的位置,再次点击时,它向下移动并与第二个视图保持重叠。当这种情况发生时,顶部的 RecyclerView
会改变高度,因为它被限制在第一个视图中,否则它会留下一个空的 space.
到目前为止一切顺利,动画运行良好,但是当用户点击按钮太快时会出现问题,导致以下错误:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
在调查发生了什么之后,我发现这个问题是我用来动画更改的 TransitionManager
的结果。我发现的很有趣,当点击按钮将第一个视图向上(或向下,想象一下相反的步骤)时,经理正在执行以下操作:
- 从
RecyclerView
中淡出 first/last 视图(取决于您是否启用了反向布局或堆栈)
- 从
RecyclerView
中删除该视图
- 降低
RecyclerView
的高度
- 将第一个视图上移
尽管我在所有我能想到的地方都指定了 RecyclerView
不应该为项目更改设置动画,但 TransitionManager
覆盖了它,这意味着 window 当即将从 RecyclerView
中删除的相同视图可以再次添加到同一父级,而 window 是视图被管理器淡出的时候。
由于淡入淡出动画不是那么快,用户可以很容易地在此期间点击按钮两次,导致管理器重新添加已经在 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);
pskink post 编辑了评论中的答案,但在要求他两次 post 作为我接受但从不这样做的答案之后,我会 post而是将其标记为已回答。
TransitionManager
有一个方法 excludeChildren
非常适合我正在寻找的东西。您可以使用 by class 类型,children 的特定视图等等。
编辑:请求添加示例
AutoTransition autoTransition = new AutoTransition();
autoTransition.excludeChildren(R.id.recyclerView, true);
TransitionManager.beginDelayedTransition(constraintLayout, autoTransition);
将 constraintLayout
作为目标视图的 parent,将 R.id.recyclerView
作为我不想要的 parent 的 child 视图是动画的,在这个具体的例子中就是这样。您还可以排除属于特定 class(例如 EditText
)的所有 children,依此类推。
我是这样修复的:
TransitionManager.beginDelayedTransition(
constraintLayout,
TransitionSet().apply {
ordering = TransitionSet.ORDERING_SEQUENTIAL
addTransition(ChangeBounds())
addTransition(Fade(Fade.IN))
}
)
它与 AutoTransition
中的代码几乎相同,如果我们不通过自定义转换,这是默认代码,但我删除了 addTransition(Fade(Fade.OUT))
这似乎是导致碰撞。至少对我来说,动画看起来与原版非常相似。
我正在尝试将 ConstraintLayout
与随动画上下滑动的视图结合使用。
这些视图是垂直组织的,顶部有一个 RecyclerView
,下面堆叠了另外两个视图:
<constraint layout container>
[ ]
[ recycler view ]
[ ]
[48dp height 1st view]
[48dp height 2nd view]
</constraint layout container>
动画非常简单:点击按钮时,第一个视图从容器底部移动到您可以在上方看到的位置,再次点击时,它向下移动并与第二个视图保持重叠。当这种情况发生时,顶部的 RecyclerView
会改变高度,因为它被限制在第一个视图中,否则它会留下一个空的 space.
到目前为止一切顺利,动画运行良好,但是当用户点击按钮太快时会出现问题,导致以下错误:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
在调查发生了什么之后,我发现这个问题是我用来动画更改的 TransitionManager
的结果。我发现的很有趣,当点击按钮将第一个视图向上(或向下,想象一下相反的步骤)时,经理正在执行以下操作:
- 从
RecyclerView
中淡出 first/last 视图(取决于您是否启用了反向布局或堆栈) - 从
RecyclerView
中删除该视图
- 降低
RecyclerView
的高度
- 将第一个视图上移
尽管我在所有我能想到的地方都指定了 RecyclerView
不应该为项目更改设置动画,但 TransitionManager
覆盖了它,这意味着 window 当即将从 RecyclerView
中删除的相同视图可以再次添加到同一父级,而 window 是视图被管理器淡出的时候。
由于淡入淡出动画不是那么快,用户可以很容易地在此期间点击按钮两次,导致管理器重新添加已经在 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);
pskink post 编辑了评论中的答案,但在要求他两次 post 作为我接受但从不这样做的答案之后,我会 post而是将其标记为已回答。
TransitionManager
有一个方法 excludeChildren
非常适合我正在寻找的东西。您可以使用 by class 类型,children 的特定视图等等。
编辑:请求添加示例
AutoTransition autoTransition = new AutoTransition();
autoTransition.excludeChildren(R.id.recyclerView, true);
TransitionManager.beginDelayedTransition(constraintLayout, autoTransition);
将 constraintLayout
作为目标视图的 parent,将 R.id.recyclerView
作为我不想要的 parent 的 child 视图是动画的,在这个具体的例子中就是这样。您还可以排除属于特定 class(例如 EditText
)的所有 children,依此类推。
我是这样修复的:
TransitionManager.beginDelayedTransition(
constraintLayout,
TransitionSet().apply {
ordering = TransitionSet.ORDERING_SEQUENTIAL
addTransition(ChangeBounds())
addTransition(Fade(Fade.IN))
}
)
它与 AutoTransition
中的代码几乎相同,如果我们不通过自定义转换,这是默认代码,但我删除了 addTransition(Fade(Fade.OUT))
这似乎是导致碰撞。至少对我来说,动画看起来与原版非常相似。