-
-
Notifications
You must be signed in to change notification settings - Fork 1k
fix: overlapping buttons cause buttons to stop being responsive #3371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: overlapping buttons cause buttons to stop being responsive #3371
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for this PR!
@@ -291,6 +291,15 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R | |||
val eventTime = event.eventTime | |||
val action = event.action | |||
|
|||
if (touchResponder != null && touchResponder !== this) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this be enough?
if (touchResponder != null && touchResponder !== this) { | |
if (touchResponder !== this) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@m-bert Using only if (touchResponder !== this) would also be true when touchResponder is null, so when no other button has grabbed the responder. In that case, we want to proceed normally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, you're right 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked more into it and it seems that this change breaks buttons with exclusive={false}
.
Consider this example:
<GestureHandlerRootView>
<View style={styles.container}>
<BaseButton
exclusive={false}
style={styles.button}
shouldCancelWhenOutside={true}
onHandlerStateChange={(event) => console.log(event.nativeEvent)}>
<Text>Behind</Text>
</BaseButton>
<BaseButton
exclusive={false}
style={styles.button}
shouldCancelWhenOutside={true}
onHandlerStateChange={(event) => console.log(event.nativeEvent)}>
<Text>On top</Text>
</BaseButton>
</View>
</GestureHandlerRootView>
Now buttons are not stacked on each other and with exclusive
set to false
you should be able to click both of them at the same time. However, with these changes it is not possible.
@m-bert I added a check to verify if the button is exclusive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, when both buttons have exclusive={false}
, this problem is still reproducible 😞
@@ -296,6 +296,17 @@ class RNGestureHandlerButtonViewManager : ViewGroupManager<ButtonViewGroup>(), R | |||
val eventTime = event.eventTime | |||
val action = event.action | |||
|
|||
if (touchResponder != null && touchResponder !== this) { | |||
if (touchResponder!!.exclusive) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd combine it with outer if
to avoid unnecessary nesting
@m-bert What do you mean? Your example is working for me Screen_Recording_20250204_121330_example.mp4 |
I meant the original one, when the buttons are stacked one on top of the other. The button below gets blocked as in the original issue. |
@m-bert Yes, that's already happening in the latest version of react-native-gesture-handler 🤷 . If we want to fix this bug for two buttons with exclusive=false, we might need a different solution, but I’m not sure what that would be. Maybe some ray tracing and checking if there is another button on top? That sounds heavy... My PR already fixes the bug for regular buttons, and the case where two non-exclusive buttons overlap is a rare edge case. |
Yes, we are aware. We should find better solution for that. But I agree that it improves current behavior, so I'll give it a green light once You address this comment Also, You can either remove fixes from description, or open new issue so that we will know that it is still a problem. If you could do it quickly, we may include this in 2.23.0 (cc @latekvo) |
@m-bert Thanks, I updated description and pushed new commit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, will include it in the 2.23.0 👍
Description
Partially resolves problem in #3370
This PR fixes an issue where a behind button could stay stuck in the "pressed" state if another overlapping button took the responder. By adding a check in onTouchEvent, we ensure that only one button can stay pressed at a time. If another button is already the responder, the behind button cancels itself and won't remain highlighted.
It will not solve the issue if both button are not exclusive. For this edge case better solution is needed.
With this fix:
withFix.mp4
Without this fix:
withoutFix.mp4
Test plan
https://snack.expo.dev/@oblador/gesture-handler-overlap-reproduction
Collapsed test code