yennsarah
yennsarah

Reputation: 5517

Android Animating Constraint Layouts

I want to animate two ConstraintLayouts - one being the child of another.

I know that animations only work on direct childs of an ConstraintLayout, so this is my layout:

<android.support.constraint.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:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.constraint.ConstraintLayout
        android:id="@+id/cl"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="#393939"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:visibility="visible">

        <TextView
            android:id="@+id/textview"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Move me!"
            android:textColor="#fff"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.8" />
    </android.support.constraint.ConstraintLayout>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Animate" />
</android.support.constraint.ConstraintLayout>

Which has a ConstraintLayout as root layout and an inner ConstraintLayout which has a background color and a TextView. The inner layout is set to gone in the beginning.

I want to fade in the inner ConstraintLayout (set its visibility to View.VISIBLE) and also move the TextView up (set its vertical Bias to a lower number). Since I can't animate inner Child views, I create 4 Constraint Sets - csA for the visibility animation of the inner ConstraintLayout and csB for the animation to move the TextView upwards.

class MainActivity : AppCompatActivity() {
    val csA1 = ConstraintSet()
    val csA2 = ConstraintSet()

    val csB1 = ConstraintSet()
    val csB2 = ConstraintSet()

    lateinit var btn: Button
    lateinit var cl: ConstraintLayout
    lateinit var root: ConstraintLayout

    var switch = false


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        root = findViewById(R.id.root_layout)
        val tv: TextView = findViewById(R.id.textview)
        cl = findViewById(R.id.cl)
        btn = findViewById(R.id.button)

        btn.setOnClickListener { toggle() }

        csA1.clone(root)
        csA2.clone(csA1)
        csA2.setVisibility(R.id.cl, View.VISIBLE)

        csB1.clone(cl)
        csB2.clone(csB1)
        csB2.setVerticalBias(R.id.textview, 0.3f)

    }

    fun toggle() {
        TransitionManager.beginDelayedTransition(root)
        val cs = if (!switch) csA2 else csA1
        cs.applyTo(root)
        val vsB = if (!switch) csB2 else csB1

        TransitionManager.beginDelayedTransition(cl)
        vsB.applyTo(cl)

        switch = !switch
        btn.text = "switch: $switch"
    }
}

The first button press may work - but on the second press, the layout does not get hidden, and the view stays where it is. The text gets cut to the first letter, full text is shown on the next click. When the trigger is then set from true to false, the background blinks to white for a really short time, then goes to grey again.

There is nothing else in that project. If I disable one of the animations, the other is working without any problem.

What I have tried:

   
    Handler().postDelayed({
        TransitionManager.beginDelayedTransition(cl)
        vsB.applyTo(cl)
    }, 450)
   
    fun toggle() {
        val duration = 200L
        val transitionA = AutoTransition()
        transitionA.duration = duration

        val transitionB = AutoTransition()
        transitionB.startDelay = duration

        TransitionManager.beginDelayedTransition(root, transitionA)
        val cs = if (!switch) csA2 else csA1
        cs.applyTo(root)

        val vsB = if (!switch) csB2 else csB1

        TransitionManager.beginDelayedTransition(cl,transitionB)
        vsB.applyTo(cl)

        switch = !switch
        btn.text = "switch: $switch"
    }

I tested this on an emulator on API 27 and a Samsung S6 on API 24. Other technical info:

   
    compileSdkVersion 27

    minSdkVersion 21
    targetSdkVersion 27

    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support.constraint:constraint-layout:1.1.0'


    Android Studio Version 3.1.2
    Android SDK Tools 26.1.1 

Is the simultaneous animation of two ConstraintLayouts even possible?

Upvotes: 6

Views: 2877

Answers (1)

IntersectGlasses
IntersectGlasses

Reputation: 53

Since I still can't comment (not enough rep), I'll write it here, but read it like a comment.
You are thinking of ConstraintSets wrong.
If you just want to set some stuff visible and animate it to another location, you need to make two .xml's. They need to have the same views inside (no matter if visible or not) and then apply them via TransitionManager and ConstraintSets.
Simple example without code:

You have a ConstraintLayout xml with one ImageView in it. In the first xml it's set to be at the top of the Layout, in the second you have set it to the bottom. When you now clone these layouts and apply one to another (on a button click probably), then it will animate the ImageView from the top to the bottom.

Have another look at the official doc and try it like that. If you understand it once, it's actually quite easy. If you have further questions or want me to give you a better example, just ask.

Upvotes: 2

Related Questions