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:
vsB
via Handler & postDelayed
as well as setting a custom transition with a startDelay
with the duration
of the visibility animation.
Handler().postDelayed({
TransitionManager.beginDelayedTransition(cl)
vsB.applyTo(cl)
}, 450)
With the handler and a delay of 450 ms
(I did not test the minimum limit of this) - the animation does work. It does not lag, the layout gets shown and hidden properly on every button press and the textview moves upwards. But that's not quite my requirement. I need to animate them simultaneously, or even better: with a delay of 50ms on the upwards movement.
With the handler and a delay of 1 ms
, the layout is shown on first press, the TextView
is already in its final position (no movement).
Custom transition with a startDelay
, which reacts like the version without anything: TextView.text
gets cut to the first letter, background blinks to white and goes back to gray. The transitions to not seem to have any effect, not even with a greater startDelay
(duration + 200
, for example).
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?
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.
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