I am running into an issue using MotionLayout
where a user cannot swipe up/down if they start their swipe on a clickable item. I want the user to be able to swipe over any part of the screen, and the swiping transition is triggered.
Basically, the behavior will be very similar to what is currently on the Yelp app for Android. Swiping up anywhere on the screen moves the search bar to the top of the screen. See this video of the swiping behavior.
My code for the transition looks something like this:
<Transition
app:constraintSetStart="@id/start"
app:constraintSetEnd="@id/end"
>
<OnSwipe
app:dragDirection="dragUp"
app:onTouchUp="decelerate"
/>
</Transition>
My code for the MotionLayout
looks something like this:
<androidx.constraintlayout.motion.widget.MotionLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutDescription="@xml/motion_scene">
>
<!-- other views -->
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title"
android:textColor="@color/black"
android:textSize="14sp"
android:lineSpacingExtra="7sp"
android:fontFamily="@font/avenir"
android:layout_marginBottom="16dp"
/>
<GridView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numColumns="2"
android:verticalSpacing="8dp"
android:horizontalSpacing="12dp"
android:stretchMode="columnWidth"
tools:listitem="@layout/griditem" <!-- This layout file contains a single <Button/> -->
/>
</LinearLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>
Here are all of the things I have tried and couldn't get to work:
- Overriding
onInterceptTouchEvent
in theViewGroup
parent of the clickable view (Just returning true here will result in the swiping behavior I want, but then the children views that should be clickable no longer are.)
override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
if (ev?.action == MotionEvent.ACTION_DOWN) {
onTouchEvent(ev)
return false
}
return true
}
- Overriding
onTouchEvent
in the clickable child view
override fun onTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_DOWN) {
super.onTouchEvent(event)
return false
}
return super.onTouchEvent(event)
}
- Overriding
onInterceptTouchEvent
in theMotionLayout
override fun onInterceptTouchEvent(event: MotionEvent?): Boolean {
if (event?.action == MotionEvent.ACTION_MOVE) {
return super.onInterceptTouchEvent(event)
}
return false
}
I have looked at all of these StackOverflow posts (and more but these are the most relevant):
- MotionLayout problems with children intercepting touch events
- Can we use OnSwipe and OnClick in the same transition for Android MotionLayout?
- How to handle OnClick and OnClickListener in MotionLayout similar to YouTube
- MotionLayout OnSwipe and OnClick on same view
- MotionLayout prevents click listener on all views
- MotionLayout - How to limit the OnSwipe event on a specific view instead of on whole screen
Any ideas as to what I could do here to be able to both swipe and click on items?
I got it working. Two things here that helped:
app:touchAnchorId
to the id of the RecyclerView.setTransition
to reset the transition back to the OnSwipe transition when appropriate.I hope that helps someone who runs into this problem.