Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to animate the nested view on constraint layout?

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>
  • If I need to go with constraintSet how to restructure my layout (without nested groups)?
  • Is there any other way we can achieve it? I feel like 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:

enter image description here

like image 371
Balasubramanian Avatar asked Jan 08 '21 04:01

Balasubramanian


People also ask

Can we use RelativeLayout inside ConstraintLayout?

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.

How does MotionLayout work?

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.

Are nested constraint layouts bad?

“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.

Why doesn't constraintlayout have animations for each view?

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.

Is it okay to have nested constraint layout?

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.

Can constraintlayout handle nested viewgroups?

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.

What are the disadvantages of using constraintlayout?

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.


Video Answer


1 Answers

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)

enter image description here

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().

like image 63
Lalit Fauzdar Avatar answered Oct 18 '22 02:10

Lalit Fauzdar