Search code examples
androidandroid-motionlayout

Motion layout. OnSwipe doesn't handle correctly drag event. What is the root problem?


So, I have simple scene:

 <Transition
        motion:constraintSetStart="@id/motion_01_cl_start"
        motion:constraintSetEnd="@id/motion_01_cl_end"
        motion:duration="300">

    <OnSwipe
        motion:touchRegionId="@id/imageView"
        motion:dragDirection="dragUp"/>
</Transition>


<ConstraintSet android:id="@+id/motion_01_cl_start">
    <Constraint
            android:id="@+id/testView"
            android:layout_width="200dp"
            android:layout_height="250dp"

            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            android:layout_marginTop="0dp"
            android:elevation="3dp"/>

    <Constraint
            android:id="@+id/imageView"
            android:layout_width="200dp"
            android:layout_height="250dp"

            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            android:layout_marginTop="0dp"
            android:elevation="4dp"/>

</ConstraintSet>

<ConstraintSet android:id="@+id/motion_01_cl_end">
    <Constraint
            android:id="@+id/testView"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:elevation="10dp"
            android:layout_marginTop="100dp"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
    />

    <Constraint
            android:id="@+id/imageView"
            android:layout_width="200dp"
            android:layout_height="290dp"
            android:elevation="25dp"
            android:layout_marginTop="40dp"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
    />
</ConstraintSet>

As you may see, in Transition I have swipe handling with dragDirection "dragUp". But problem is that it works as dragDown, can't understand why. I tried to set dragDirection to dragDown, but it works as expected. Is there is any problems with direction handling?

Here is my layout:

<androidx.constraintlayout.motion.widget.MotionLayout
        android:layout_width="match_parent"
        app:layoutDescription="@xml/scene"
        android:layout_height="match_parent"
        android:id="@+id/motionLayout">

    <androidx.cardview.widget.CardView
            android:id='@+id/testView'
            android:layout_height="400dp"
            android:layout_width="300dp"/>


    <ImageView
           android:layout_width="300dp"
           android:layout_height="400dp"
           android:id="@+id/imageView"
           android:src="@drawable/img"
           android:scaleType="centerInside"/>
</androidx.constraintlayout.motion.widget.MotionLayout>

Do you now why I may have this problem?


Solution

  • why onSwipe does not handle correct drag event?

    The drag direction is decided by the MotionLayout rendering engine itself based on the placement of the touchAnchorId.

    To work around this, add a dummy view as the touchAnchorId and add sliding animation for that view in the required direction. Since we don't need to make this dummy view visible on the UI, we can use the 'Space' view provided by the android SDK as the dummy view.

     <Space
            android:id="@+id/space"
            android:layout_width="1dp"
            android:layout_height="1dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    

    Add ConstraintLayout dependency into your build.gradle file

    dependencies {
        implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
    }
    

    So, your layout and motion resource files will look like given below

    activity_main.xml

    <androidx.constraintlayout.motion.widget.MotionLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:motion="http://schemas.android.com/apk/res-auto"
        android:id="@+id/motionLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        motion:layoutDescription="@xml/motionscene">
    
        <androidx.cardview.widget.CardView
            android:id='@+id/testView'
            android:layout_height="400dp"
            android:layout_width="300dp"/>
    
    
        <ImageView
            android:layout_width="300dp"
            android:layout_height="400dp"
            android:id="@+id/imageView"
            android:src="@drawable/abd"
            android:scaleType="centerInside"/>
        <Space
            android:id="@+id/space"
            android:layout_width="1dp"
            android:layout_height="1dp"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.motion.widget.MotionLayout>
    

    motionscene.xml

    <MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:motion="http://schemas.android.com/apk/res-auto">
        <Transition
            motion:constraintSetStart="@id/motion_01_cl_start"
            motion:constraintSetEnd="@id/motion_01_cl_end"
            motion:duration="300">
    
            <OnSwipe
                motion:touchAnchorId="@id/space"
                motion:dragDirection="dragUp"/>
        </Transition>
    
    
        <ConstraintSet android:id="@+id/motion_01_cl_start">
            <Constraint
                android:id="@+id/testView"
                android:layout_width="200dp"
                android:layout_height="250dp"
    
                motion:layout_constraintBottom_toBottomOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintTop_toTopOf="parent"
                motion:layout_constraintEnd_toEndOf="parent"
                android:layout_marginTop="0dp"
                android:elevation="3dp"/>
    
            <Constraint
                android:id="@+id/imageView"
                android:layout_width="200dp"
                android:layout_height="250dp"
    
                motion:layout_constraintBottom_toBottomOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintTop_toTopOf="parent"
                motion:layout_constraintEnd_toEndOf="parent"
                android:layout_marginTop="0dp"
                android:elevation="4dp"/>
            <Constraint
                android:id="@+id/space"
                motion:layout_constraintBottom_toBottomOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                />
        </ConstraintSet>
    
        <ConstraintSet android:id="@+id/motion_01_cl_end">
            <Constraint
                android:id="@+id/testView"
                android:layout_width="300dp"
                android:layout_height="300dp"
                android:elevation="10dp"
                android:layout_marginTop="100dp"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintTop_toTopOf="parent"
                motion:layout_constraintEnd_toEndOf="parent"
                />
    
            <Constraint
                android:id="@+id/imageView"
                android:layout_width="200dp"
                android:layout_height="290dp"
                android:elevation="25dp"
                android:layout_marginTop="40dp"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintTop_toTopOf="parent"
                motion:layout_constraintEnd_toEndOf="parent"
                />
            <Constraint
                android:id="@+id/space"
                motion:layout_constraintTop_toTopOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                />
        </ConstraintSet>
    </MotionScene>
    

    and the output will look like the below gif

    gif image showing sample animation