gastonbs
gastonbs

Reputation: 43

Android Motion Layout does not adapt to dynamic change in TextView content before animation. So how to make it adapt to new contents?

If we programmatically change the content of a Textview, after that the Motion animation only consider the original height of the TextView.

This example is suppose to expand to show a textView contents. It works if the content is previously assigned in the xml layout. But if the content is assigned programmatically and it takes several lines it only expand one line.

Code to trigger the Motion Scene Transition:

        binding.button.setOnClickListener {

            binding.tvLorem.text = LongText
            binding.motionLayout.transitionToEnd()
        }
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout
    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:id="@+id/motionLayout"
    tools:context=".MotionaLayoutActivity"
    tools:showPaths="true"
    app:layoutDescription="@xml/activity_motiona_layout_scene">
  
    <View
        android:id="@+id/button"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:background="@color/design_default_color_primary"
        android:text="Button" />

    <TextView
        android:id="@+id/tvLorem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Lorem Ipsum"
        />

    <View
        android:id="@+id/bottomBar"
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:background="@color/design_default_color_secondary"
        app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.motion.widget.MotionLayout>

The file with the MotionScene:

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">

<ConstraintSet android:id="@+id/start">

    <Constraint
        android:id="@+id/button"
        android:layout_width="64dp"
        android:layout_height="64dp"
        motion:layout_constraintBottom_toTopOf="@id/tvLorem"
        motion:layout_constraintEnd_toEndOf="parent" />

    <Constraint
        android:id="@+id/tvLorem"
        android:visibility="visible"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginTop="@dimen/default_margin"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintBottom_toTopOf="@id/bottomBar">

        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#00000000"/>

    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/end">
    <Constraint
        android:id="@+id/button"
        android:layout_width="64dp"
        android:layout_height="64dp"
        motion:layout_constraintBottom_toTopOf="@id/tvLorem"
        motion:layout_constraintEnd_toEndOf="parent" />

    <Constraint
        android:id="@+id/tvLorem"
        android:visibility="visible"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/cardview_dark_background"
        android:layout_marginTop="@dimen/default_margin"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintBottom_toTopOf="@+id/bottomBar">

        <CustomAttribute
            motion:attributeName="backgroundColor"
          motion:customColorValue="@color/cardview_dark_background"/>

    </Constraint>

</ConstraintSet>

<Transition
    motion:constraintSetStart="@+id/start"
    motion:constraintSetEnd="@+id/end"
    motion:duration="1000">
    <OnClick
        motion:touchAnchorId="@+id/button"
        motion:touchAnchorSide="right"
        motion:dragDirection="dragRight" />
</Transition>

</MotionScene>

So, how to make it work changing the text content programmatically?

For the moment I tried:

        binding.tvLorem.invalidate()
        binding.tvLorem.postInvalidate()
        binding.motionLayout.invalidate()
        binding.motionLayout.clearAnimation()
        binding.motionLayout.rebuildScene()

and nothing works!

What do works is changing the TextView visibility to GONE and VISIBLE before running the transition.

fun TextView.informMotionSceneAboutNewHeight(){
    visibility = View.GONE
    visibility = View.VISIBLE
}

binding.tvLorem.text = LongText
binding.tvLorem.informMotionSceneAboutNewHeight()
binding.motionLayout.transitionToEnd()

Upvotes: 0

Views: 215

Answers (1)

ronny monta&#241;o
ronny monta&#241;o

Reputation: 31

I faced a similar issue, and found that the problem was caused by using the same ID name in another XML file. To solve the problem, I changed the name of

Upvotes: 0

Related Questions