0

I have two layout files which I am using to do the start and end transition using a motion layout.

The text moves as expected, based on start layout file to end layout file. But the text size does not change, even though different text sizes have been defined in each of the two layouts.

Could someone please help? The files have been provided below:

motion_layout_start.xml

<androidx.constraintlayout.motion.widget.MotionLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:showPaths="true">


        <TextView
            android:id="@+id/title"
            android:layout_width="@dimen/match_constraints"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toTopOf="@id/description"
            android:text="HEADING"
            style="@style/TextStyle.Title"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_constraintVertical_bias="0"/>

        <TextView
            android:id="@+id/description"
            android:layout_width="@dimen/match_constraints"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/title"
            app:layout_constraintBottom_toTopOf="@+id/recycler_view"
            tools:text="DESCRIPTION"
            style="@style/TextStyle.DESC"/>


        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_height="@dimen/match_constraints"
            android:layout_width="match_parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/description"
            app:layout_constraintBottom_toBottomOf="parent" />



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

motion_layout_end.xml

<androidx.constraintlayout.motion.widget.MotionLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:showPaths="true">


        <TextView
            android:id="@+id/title"
            android:layout_width="@dimen/match_constraints"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toTopOf="@id/recycler_view"
            android:text="HEADING"
            style="@style/TextStyle.SmallTitle"
            app:layout_constraintVertical_chainStyle="packed"
            app:layout_constraintVertical_bias="0"/>


        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_height="@dimen/match_constraints"
            android:layout_width="match_parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/title"
            app:layout_constraintBottom_toBottomOf="parent" />

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

motion xml file fragment_motion.xml

<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto">


    <Transition
        app:constraintSetStart="@layout/motion_layout_start"
        app:constraintSetEnd="@layout/motion_layout_end">

        <OnSwipe app:touchAnchorSide="top"
            app:touchAnchorId="@id/recycler_view"
            app:dragDirection="dragUp"
            app:moveWhenScrollAtTop="true"/>
    </Transition>


</MotionScene>

Thanks

Sunny
  • 7,444
  • 22
  • 63
  • 104

1 Answers1

0

While having your MotionLayout interpolate between two ConstraintLayouts is technically supported, you can get a lot more functionality by creating a self-contained MotionScene Benefits of using a self-contained MotionScene

The above image is a screenshot from a very useful Medium article linked here.

In order to get your text to change size as you desire, you can make a few small changes to contain most of the functionality in the motion scene file. Note that while I tried my best to create these files based on your given code, it may need some tweaking to work properly in your code.

First, create a motionLayout file (called whatever you like, I called mine motion_layout.xml) that looks like this:

<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"
    app:layoutDescription="@xml/fragment_motion"
    tools:showPaths="true">

    <TextView
        android:id="@+id/title"
        style="@style/TextStyle.Title"
        android:layout_width="@dimen/match_constraints"
        android:layout_height="wrap_content"
        android:text="HEADING" />

    <TextView
        android:id="@+id/description"
        style="@style/TextStyle.DESC"
        android:layout_width="@dimen/match_constraints"
        android:layout_height="wrap_content"
        tools:text="DESCRIPTION" />


    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="@dimen/match_constraints" />

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

There are a few important things to note here. First, note the app:layoutDescription="@xml/fragment_motion" within the MotionLayout. This defines where the motion is defined. Also, all the constraints have been stripped out of this file. That's because the constraints will now be defined in the motion scene.

You'll want to make sure that in your activity the layout that you inflate is the above motion layout.

Next, we need to add a few constraint sets to your MotionScene. That will look like the following:

<MotionScene xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <Transition
        app:constraintSetStart="@id/start"
        app:constraintSetEnd="@id/end">

        <OnSwipe app:touchAnchorSide="top"
            app:touchAnchorId="@id/recycler_view"
            app:dragDirection="dragUp"
            app:moveWhenScrollAtTop="true"/>
    </Transition>

    <ConstraintSet
        android:id="@+id/start">
        <Constraint
            android:id="@id/title">
            <Layout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintEnd_toEndOf="parent"/>
            <CustomAttribute
                app:attributeName="textSize"
                app:customFloatValue="24"/>
        </Constraint>

        <Constraint
            android:id="@id/description">
            <Layout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/title"/>
        </Constraint>

        <Constraint
            android:id="@id/recycler_view">
            <Layout
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/description"/>
        </Constraint>

    </ConstraintSet>

    <ConstraintSet
        android:id="@+id/end">
        <Constraint
            android:id="@id/title">
            <Layout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintEnd_toEndOf="parent"/>
            <CustomAttribute
                app:attributeName="textSize"
                app:customFloatValue="14"/>
        </Constraint>

        <Constraint
            android:id="@id/description">
            <Layout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/title"/>
        </Constraint>

        <Constraint
            android:id="@id/recycler_view">
            <Layout
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/description"/>
        </Constraint>
    </ConstraintSet>

</MotionScene>

You'll notice that the textSize is set as a customAttribute on the title. It may seem weird to set a float value for the textSize but it will call setTextSize behind the scenes which will automatically apply scalable pixels as it interprets it as text and that is best practices.

Comment if you have any questions. There are some great examples, again, in this blog series

kjanderson2
  • 1,209
  • 12
  • 23