I have a requirement where the view needs to be at the center of bottom and adjust the height based on its content. So created constraint layout
inside root constraint layout
to acheive this. But now I am facing a problem with animation. I am not able to apply 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
how to restructure my layout (without nested groups)?constraintSet
is much straight forward to use.Tried calling this animation constraint set which will pass nested constraint as param error_layout
. But no changes on the result:
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);
}
Layout:
It's not the right way. ConstraintLayout came to prevent the usage of nested layouts. Remove the relative layout and put a view on top(zindex) of your clickable zone.
MotionLayout bridges the gap between layout transitions and complex motion handling, offering a mix of features between the property animation framework, TransitionManager , and CoordinatorLayout . In addition to describing transitions between layouts, MotionLayout lets you animate any layout properties, as well.
“Using nested instances of LinearLayout can lead to an excessively deep view hierarchy. Furthermore, nesting several instances of LinearLayout that use the layout_weight parameter can be especially expensive as each child needs to be measured twice.
If not, providing animations for each of the views will be a tiresome job. ConstraintLayout will only perform animation on its direct children since it only knows when you change layout parameters and constraints on the children that it handles. It may not handle ViewGroups well.
So generally is it alright to have nested Constraint Layout or it will be a wrong practice regarding the purpose of it (i.e. having flat layout)? As in answers there are suggestions for setting listener for each of these views instead of setting it for their parent layout, I have already tested this approach and it is not what I need.
ConstraintLayout will only perform animation on its direct children since it only knows when you change layout parameters and constraints on the children that it handles. This means that it won’t handle nested ViewGroups very nicely.
ConstraintLayout will only perform animation on its direct children since it only knows when you change layout parameters and constraints on the children that it handles. It may not handle ViewGroups well.
Remember, ConstraintSet Animation works as any other animation with two stages - Animation Start and Animation End. So, First set the view constraint as Animation start which means hidden under bottom of the layout.
So, Change the initial constraints as:
<!-- 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">
Then, create the constraints as
//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)
Then, if you want to hide it again. Just replace the TOP and BOTTOM as
constraintSet.clear(error_layout.id, ConstraintSet.BOTTOM)
constraintSet.connect(error_layout.id, ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM)
GIF took more time than coding :p.
EDIT - To listen to animation updates, especially Animation end as requested, what you can do is you can set a listener on 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) {
}
})
Put it just before the beginDelayedTransition()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With