I'v got a Fragment
that hosts a RecyclerView
within a MotionLayout
. On top of the recycler view I've got a view that collapses and expands, all done in my motion scene. It is triggered by a click as well as responding to dragging the recycler view. So far this all works as intended.
Now comes the crux: I'd like to hide the collapsing views completely for some states within my app. But if I set the views visibility or change its height, it still comes back into view when I drag the recyclerview.
So is it possible to disable the MotionLayout completely (Lock the constraints) until I enable it again. To disable the drag recogniser would also be a viable solution.
Now some simplified XML to demonstrate the situation.
The layout containing the motion layout with header view and recyclerview
<?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:id="@+id/favouritesMotionLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/favourites_motion_scene"
android:animateLayoutChanges="true">
<ImageView
android:id="@+id/headerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
/>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
...
>
<androidx.recyclerview.widget.RecyclerVieww
android:id="@+id/favoritesList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>
The corresponding motion scene:
<?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"
>
<Transition
motion:constraintSetStart="@id/expanded"
motion:constraintSetEnd="@id/collapsed"
motion:duration="300">
<OnSwipe
motion:touchAnchorId="@id/swipeRefreshLayout"
motion:touchAnchorSide="top"
motion:dragDirection="dragUp" />
</Transition>
<ConstraintSet android:id="@+id/expanded">
... Constraints for expanded header ...
</ConstraintSet>
<ConstraintSet android:id="@+id/collapsed">
... ... Constraints for collapsed header ...
</ConstraintSet>
</MotionScene>
Using constraint layout version "2.0.0-alpha3"
implementation "com.android.support.constraint:constraint-layout:2.0.0-alpha3"
So recap: I'd like to be able to disable the motion layout, so that I can scroll the recyclerview without the header expanding, until I tell it to be enabled again.
Unfortunately it is not as easy as favouritesMotionLayout.isEnabled = false
, but that is the way I was thinking.
Now with ConstraintLayout beta 2 you can! This is the official way to do it:
motionLayout.getTransition(R.id.yourTransition).setEnable(false)
Recently I've been hacking around MotionLayout a lot, so far I found my trick to disable Motionlayout is like below.
layoutContainer.setTransitionListener(object: MotionLayout.TransitionListener {
override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}
override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {}
override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {}
override fun onTransitionChange(p0: MotionLayout?, startedScene: Int, endScene: Int, p3: Float) {
when(currentFragmentTag) {
TAG_DEFAULTBACKGROUND -> {
if( startedScene==R.id.halfExpanded ) {
layoutContainer.transitionToState(startedScene)
}
}
}
}
})
So basically, I'm telling to MotionLayout to go back on certain situations.
I feel like onTransitionTrigger
or onTransitionStarted
should contain the stopping function but it won't listen at those moments.
onTransitionChange
is where it actually starts moving.
I think you'll get the point of this trick vice versa.
Happy coding!
Actually, i managed to get it working by setting the start state of my scene for both start and end. In kotlin:
motionLayout.setTransition(R.id.start, R.id.start)
And when i needed to enable my layout:
motionLayout.setTransition(R.id.start, R.id.end)
No need to change your scene xml, worked flawlessly for me in alpha-03
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