Open MMKrivtsov opened 2 years ago
I am not sure what you are asking for:
MotionLayout should only be grabbing swipe if you have an <OnSwipe ... nestedScrollFlags="disableScroll" />
I have a layout with vertical RecyclerView inside of MotionLayout. By default I can swipe both of them simultaneously and that works worse for me than same RecyclerView inside of ViewPager.
Two things:
You can use MotionLayout inside a ViewPager if it has the behavior you are looking for. Listen to The view pager and set progress. (https://developer.android.com/training/constraint-layout/motionlayout/examples#viewpager)
Still not sure the behavior you are asking for. In general I do not recommend using touchRegionId its behavior is unpredictable. (But cannot be change because legacy)
Link you provided shows how to use MotionView alongside of ViewPager, not inside. of it. Would not swiping of view pager move child MotionLayout out of view?
If you look inside of HorizontalScrollView
class method onInterceptTouchEvent
- it does return whether it is being swiped or not, not true
as MotionLayout. does. I ask for MotionLayout
to work similarly by returning current transition's touch response's value of mDragStarted instead of true in 'onInterceptTouchEvent`. This way it works as expected, but i have to use some reflection calls to achieve this.
For backwards compatibility it can be toggled behavior with additional attribute. By default - return true from onInterceptTouchEvent
, if attribute is set - return 'mDragStarted'.
I think I get it. I will leave this open till I fix it.
I'm having an issue that's I believe may be closely related to what is being described in this issue.
Given that I have a Motion Layout with a Horizontal RecyclerView. Horizontal Recycler Views seem to prevent MotionLayout transitions from taking place. However, Vertical Recycler Views seems to correctly trigger the MotionLayout transition when scroll interaction takes place.
I've tried using the flag added in commit 9ec3c08, however there is no change to the behavior.
I've created this example project to showcase the issue: Layout: activity_main.xml Motion Scene: motion_layout_scene.xml Activity: (MainActivity.kt)[https://github.com/blad/motion-layout-recycler-view-issue/blob/main/ap
RecyclerView's default behavior is to consumes drag events. You can see this by adding a line if (horizontal) rv.suppressLayout(true) to configure. This is probably a know issues with RecyclerView that cannot be fixed with out breaking compatibility. For more information: Bug: RecyclerView should not interfere with opposite direction scroll touch events Example Workaround: Fixing RecyclerView nested scrolling in opposite direction
Thank you for your reply John.
Unfortunately the workaround linked does not directly work for my use case.
However it does make it clear that I would possibly need to override MotionLayout
's onInterceptTouchEvent
method so that I would have any hope of the nested RecyclerView not consuming the event before MotionLayout can react appropriately.
Knowing that, I did find a workaround of wrapping the horizontal RecyclerView
in a NestedScrollView
with vertical orientation.
I suppose that the NestedScrollView
handles the vertical drags and allows the parent to MotionLayout to react correctly.
Leading to something like:
<!-- pseudo-layout xml -->
<MotionLayout>
<NestedScrollView android:orientation="vertical" android:layout_height="wrap_content">
<RecyclerView /> <!-- Horizontal Orientation -->
</NestedScrollView>
<RecyclerView /> <!-- Vertical Orientation -->
</MotionLayout>
activity_mail.xml: Layout with workaround wrapping NestedScrollView
Very cool approach. It works well! I will put a version of that in EamplesRecyclerView. I put examples of how to interact with RecyclerView and ConstraintLayout/MotionLayout.
Thank you for your plan. It has been a big help for me. I have already spent two whole days before that
Currently if there is scrolling view (ex. RecyclerView) inside of
MotionLayout
, this view grabs touch events preventing transitions with swipe over that view. MethodonInterceptTouchEvent
can handle and intercept touches if touch region id is set, but in that case it usesonTouchEvent
and it returns true even if touch is not swipe yet, preventing interaction with child views.I suppose it would be good to have (at least option) to return result of
this.mScene.processTouchEvent(...)
instead of true, which in turn would return result ofthis.mCurrentTransition.mTouchResponse.processTouchEvent(...)
and that one would return value ofmDragStarted
.Or at least make more getters for accessing such fields: getter for current scene in
MotionLayout
, makeTouchResponse
class public and add getter formDragStarted
inTouchResponse
. Maybe getter formCurrentTransition
inMotionScene
too, but it can be accessed withbestTransitionFor()
, so separate getter is not necessary now.