如何在约束布局上为嵌套视图设置动画?
How to animate the nested view on constraint layout?
我有一个要求,视图需要位于底部的中心,并根据其内容调整高度。所以在 root constraint layout
中创建了 constraint layout
来实现这个。但现在我面临动画问题。我无法申请 constraintSet
.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BEE">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/error_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="40dp"
android:background="#FFF"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/error_try_again"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:textStyle="bold"
android:minWidth="180dp"
android:text="Try again"
android:textAlignment="center"
android:textColor="#000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/error_subtitle" />
<TextView
android:id="@+id/error_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:textStyle="bold"
android:text="We are unable to find the object"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="21sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/error_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:text="Try to keep the camera steady"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="12sp"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/error_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
- 如果我需要
constraintSet
如何重组我的布局(没有嵌套组)?
- 有没有其他方法可以实现?我觉得
constraintSet
使用起来非常直接。
尝试调用此动画约束集,它将嵌套约束作为参数传递 error_layout
。但结果没有变化:
private void animateResult(ConstraintLayout constraint) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(this, R.layout.frameout_layout);
Transition transition = new ChangeBounds();
transition.setInterpolator(new AnticipateOvershootInterpolator(1.0f));
transition.setDuration(1200);
TransitionManager.beginDelayedTransition(constraint, transition);
constraintSet.applyTo(constraint);
}
布局:
请记住,ConstraintSet 动画与任何其他动画一样工作,有两个阶段 - 动画开始和动画结束。所以,首先将视图约束设置为动画开始,这意味着隐藏在布局底部。
因此,将初始约束更改为:
<!-- Here app:layout_constraintTop_toBottomOf will position the view under the layout/screen -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/error_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="40dp"
android:background="#fff"
android:visibility="visible"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
然后,将约束创建为
//rootLayout is the Id of the parent layout
val constraintSet = ConstraintSet()
constraintSet.clone(rootLayout)
constraintSet.clear(error_layout.id, ConstraintSet.TOP)
constraintSet.connect(error_layout.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
val transition: Transition = ChangeBounds()
transition.interpolator = AnticipateOvershootInterpolator(1.0f)
transition.duration = 1200
TransitionManager.beginDelayedTransition(rootLayout, transition)
constraintSet.applyTo(rootLayout)
然后,如果你想再隐藏它。只需将 TOP 和 BOTTOM 替换为
constraintSet.clear(error_layout.id, ConstraintSet.BOTTOM)
constraintSet.connect(error_layout.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
GIF 比编码花费的时间更多:p.
EDIT - 要收听动画更新,尤其是按要求结束动画,您可以做的是在 transition
上设置一个监听器 as
transition.addListener(object : Transition.TransitionListener {
override fun onTransitionStart(transition: Transition) {
}
override fun onTransitionEnd(transition: Transition) {
}
override fun onTransitionCancel(transition: Transition) {
}
override fun onTransitionPause(transition: Transition) {
}
override fun onTransitionResume(transition: Transition) {
}
})
把它放在 beginDelayedTransition()
之前。
我认为最简单的方法是使用转换管理器。
像这样
findViewById(R.id.button).setOnClickListener {
TransitionManager.beginDelayedTransition(constraintLayout)
val constraint = if (changed) constraintSet1 else constraintSet2
constraint.applyTo(constraintLayout)
P.S。 - 哦,我看到有人曾经说过同样的话并且有更好的解释。
我有一个要求,视图需要位于底部的中心,并根据其内容调整高度。所以在 root constraint layout
中创建了 constraint layout
来实现这个。但现在我面临动画问题。我无法申请 constraintSet
.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#BEE">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/error_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="40dp"
android:background="#FFF"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/error_try_again"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:textStyle="bold"
android:minWidth="180dp"
android:text="Try again"
android:textAlignment="center"
android:textColor="#000"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/error_subtitle" />
<TextView
android:id="@+id/error_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:textStyle="bold"
android:text="We are unable to find the object"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="21sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/error_subtitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="6dp"
android:layout_marginEnd="12dp"
android:text="Try to keep the camera steady"
android:textAlignment="center"
android:textColor="@color/black"
android:textSize="12sp"
android:visibility="visible"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/error_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
- 如果我需要
constraintSet
如何重组我的布局(没有嵌套组)? - 有没有其他方法可以实现?我觉得
constraintSet
使用起来非常直接。
尝试调用此动画约束集,它将嵌套约束作为参数传递 error_layout
。但结果没有变化:
private void animateResult(ConstraintLayout constraint) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(this, R.layout.frameout_layout);
Transition transition = new ChangeBounds();
transition.setInterpolator(new AnticipateOvershootInterpolator(1.0f));
transition.setDuration(1200);
TransitionManager.beginDelayedTransition(constraint, transition);
constraintSet.applyTo(constraint);
}
布局:
请记住,ConstraintSet 动画与任何其他动画一样工作,有两个阶段 - 动画开始和动画结束。所以,首先将视图约束设置为动画开始,这意味着隐藏在布局底部。
因此,将初始约束更改为:
<!-- Here app:layout_constraintTop_toBottomOf will position the view under the layout/screen -->
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/error_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="40dp"
android:background="#fff"
android:visibility="visible"
app:layout_constraintTop_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
然后,将约束创建为
//rootLayout is the Id of the parent layout
val constraintSet = ConstraintSet()
constraintSet.clone(rootLayout)
constraintSet.clear(error_layout.id, ConstraintSet.TOP)
constraintSet.connect(error_layout.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
val transition: Transition = ChangeBounds()
transition.interpolator = AnticipateOvershootInterpolator(1.0f)
transition.duration = 1200
TransitionManager.beginDelayedTransition(rootLayout, transition)
constraintSet.applyTo(rootLayout)
然后,如果你想再隐藏它。只需将 TOP 和 BOTTOM 替换为
constraintSet.clear(error_layout.id, ConstraintSet.BOTTOM)
constraintSet.connect(error_layout.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
GIF 比编码花费的时间更多:p.
EDIT - 要收听动画更新,尤其是按要求结束动画,您可以做的是在 transition
上设置一个监听器 as
transition.addListener(object : Transition.TransitionListener {
override fun onTransitionStart(transition: Transition) {
}
override fun onTransitionEnd(transition: Transition) {
}
override fun onTransitionCancel(transition: Transition) {
}
override fun onTransitionPause(transition: Transition) {
}
override fun onTransitionResume(transition: Transition) {
}
})
把它放在 beginDelayedTransition()
之前。
我认为最简单的方法是使用转换管理器。
像这样
findViewById(R.id.button).setOnClickListener {
TransitionManager.beginDelayedTransition(constraintLayout)
val constraint = if (changed) constraintSet1 else constraintSet2
constraint.applyTo(constraintLayout)
P.S。 - 哦,我看到有人曾经说过同样的话并且有更好的解释。