Is it possible to implement draggable panel! using motion layout?
I have tried to play around the google sample of youtube like transition by using multiple Transitions with OnSwipe on a single view but not able to succeed. Can anyone please guide me to implement how to apply the two transitions using OnSwipe on the same view?
<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Transition
app:constraintSetEnd="@id/expanded"
app:constraintSetStart="@id/collapsed"
app:duration="100"
app:interpolator="easeInOut">
<OnSwipe
app:dragDirection="dragUp"
app:maxAcceleration="200"
app:touchAnchorId="@+id/videoViewContainer"
app:touchAnchorSide="top" />
<KeyFrameSet>
<!--<KeyAttribute-->
<!--app:framePosition="0"-->
<!--app:target="@id/videoView">-->
<!--<CustomAttribute-->
<!--app:attributeName="EndPadding"-->
<!--app:customDimension="@dimen/video_view_right_padding" />-->
<!--</KeyAttribute>-->
<!--<KeyAttribute-->
<!--app:framePosition="20"-->
<!--app:target="@id/videoView">-->
<!--<CustomAttribute-->
<!--app:attributeName="EndPadding"-->
<!--app:customDimension="0dp" />-->
<!--</KeyAttribute>-->
<KeyAttribute
app:framePosition="0"
app:target="@id/videoMotionLayout">
<CustomAttribute
app:attributeName="height"
app:customDimension="90dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="20"
app:target="@id/videoMotionLayout">
<CustomAttribute
app:attributeName="height"
app:customDimension="250dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="0"
app:target="@id/videoMotionLayout">
<CustomAttribute
app:attributeName="width"
app:customDimension="160dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="20"
app:target="@id/videoMotionLayout">
<CustomAttribute
app:attributeName="width"
app:customDimension="0dp" />
</KeyAttribute>
<KeyAttribute
android:alpha="0"
app:framePosition="0"
app:target="@id/videoRecyclerView" />
<KeyAttribute
android:alpha="1"
app:framePosition="100"
app:target="@id/videoRecyclerView" />
<KeyAttribute
app:framePosition="0"
app:target="@id/videoViewContainer">
<CustomAttribute
app:attributeName="cardElevation"
app:customDimension="5dp" />
</KeyAttribute>
<KeyAttribute
app:framePosition="3"
app:target="@id/videoViewContainer">
<CustomAttribute
app:attributeName="cardElevation"
app:customDimension="0dp" />
</KeyAttribute>
</KeyFrameSet>
</Transition>
<Transition
app:constraintSetEnd="@id/close"
app:constraintSetStart="@id/close"
app:duration="100"
app:interpolator="easeInOut">
<OnSwipe
app:dragDirection="dragLeft"
app:maxAcceleration="200"
app:touchAnchorId="@+id/videoViewContainer"
app:touchAnchorSide="top" />
<KeyFrameSet>
<KeyAttribute
app:framePosition="0"
app:target="@id/videoMotionLayout">
</KeyAttribute>
</KeyFrameSet>
</Transition>
<Transition
app:constraintSetEnd="@id/close"
app:constraintSetStart="@id/close"
app:duration="100"
app:interpolator="easeInOut">
<OnSwipe
app:dragDirection="dragRight"
app:maxAcceleration="200"
app:touchAnchorId="@+id/videoViewContainer"
app:touchAnchorSide="top" />
<KeyFrameSet>
</KeyFrameSet>
</Transition>
<ConstraintSet android:id="@+id/close">
<Constraint
android:id="@id/videoViewContainer"
android:layout_height="250dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:layout_marginBottom="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Constraint
android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/videoViewContainer" />
</ConstraintSet>
<ConstraintSet android:id="@+id/collapsed">
<Constraint
android:id="@id/videoViewContainer"
android:layout_height="113dp"
android:layout_width="200dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="65dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<Constraint
android:id="@id/content"
android:layout_width="match_parent"
android:layout_height="-1dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="66dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/videoViewContainer" />
</ConstraintSet>
</MotionScene>
It would be helpful If I can move the mini-player scene to the left and right directions as well. Thank you.
How to create multiple transitions on a single view
It is possible to add multiple transitions to the same View. For example we can define animations with motion:dragDirection="dragDown"
and motion:dragDirection="dragUp"
on the same touchAnchorId
without any problem. The possible configurations are given below,
motion:dragDirection="dragUp"
motion:dragDirection="dragDown"
motion:dragDirection="dragLeft"
motion:dragDirection="dragRight"
So, here I show you how to implement all these together on the same View. Before writing any code, please see the below gif to better understand what we are trying to create.
Add the ConstraintLayout
dependency:
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
}
Create a MotionLayout file:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/motionLayout"
motion:layoutDescription="@xml/motionscene1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="240dp"
android:background="#453672"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.motion.widget.MotionLayout>
Create a MotionScene: A MotionScene is an XML resource file that contains all of the motion descriptions for the corresponding layout. Put the file under res/xml/ folder
motionscene1.xml
<?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">
<!-- top to bottom right-->
<Transition
motion:constraintSetEnd="@id/step2"
motion:constraintSetStart="@id/step1"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragDown"
motion:touchAnchorId="@id/image"
motion:touchAnchorSide="top" />
</Transition>
<!-- bottom right to bottom left-->
<Transition
motion:constraintSetEnd="@id/step3"
motion:constraintSetStart="@id/step2"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragLeft"
motion:touchAnchorId="@id/image"
motion:touchAnchorSide="left" />
</Transition>
<!-- bottom left to top-->
<Transition
motion:constraintSetEnd="@id/step1"
motion:constraintSetStart="@id/step3"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragUp"
motion:touchAnchorId="@id/image"
motion:touchAnchorSide="top" />
</Transition>
<!-- bottom right to top-->
<Transition
motion:constraintSetEnd="@id/step1"
motion:constraintSetStart="@id/step2"
motion:duration="500">
<OnSwipe
motion:dragDirection="dragUp"
motion:touchAnchorId="@id/image"
motion:touchAnchorSide="top" />
</Transition>
<!-- place the view on top-->
<ConstraintSet android:id="@+id/step1">
<Constraint
android:id="@id/image"
android:layout_width="match_parent"
android:layout_height="240dp"
android:layout_marginStart="0dp"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:layout_marginEnd="0dp"
android:layout_marginRight="0dp"
android:layout_marginBottom="0dp"
motion:layout_constraintStart_toStartOf="parent"
motion:layout_constraintTop_toTopOf="parent">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
<!-- place the view on bottom right-->
<ConstraintSet android:id="@+id/step2">
<Constraint
android:id="@id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
<!-- place the view on bottom left-->
<ConstraintSet android:id="@+id/step3">
<Constraint
android:id="@id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:layout_marginBottom="16dp"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintStart_toStartOf="parent">
<PropertySet android:alpha="1" />
</Constraint>
</ConstraintSet>
</MotionScene>
That's all. You created an amazing custom animation with out writing any java/kotlin code. MotionLayout is fully declarative, meaning that you can describe any transitions in XML, no matter how complex.