-
-
Notifications
You must be signed in to change notification settings - Fork 576
fix(Android,Fabric): pressables losing focus on screens with formSheet
presentation
#2788
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
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.
Notes for future me
if (abs(lastWidth - realWidth) < delta && | ||
abs(lastHeight - realHeight) < delta && | ||
abs(lastHeaderHeight - realHeaderHeight) < delta |
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.
This is just a catch - dunno why the realHeaderHeight
has not been diffed before - it surely should be.
// In case of form sheet we get layout notification a bit later, in `onBottomSheetBehaviorDidLayout` | ||
// after the attached behaviour laid out this view. | ||
if (changed && isNativeStackScreen && !usesFormSheetPresentation()) { |
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.
In case of formSheet
, when CoordinatorLayout
layouts it calls to the BottomSheetBehavior
to layout the child (Screen), which in turn calls CoordinatorLayout.layoutChild(Screen)
leading to a call to the overridden onLayout
method here - and this is where we would update the shadow state before.
This was not good, because at the moment of onLayout
being called, the behaviour hadn't finished its layout process yet - it later would modify top
property of the Screen, which we are interested in.
Therefore I've moved the "onlayout" callback to new method onBottomSheetBehaviorDidLayout
which is called from our ScreensCoordinatorLayout
after it has completely finished computing the layout.
I decided to not move all the code to the mentioned new callback, because the semantics are a bit different, especially the changed
parameter - in case of Screen.onLayout
it determines whether the bounds of the screen changed. In case of onBottomSheetBehaviorDidLayout
the coordinatorLayoutDidChange
informs whether coordinator layout bounds did change. I don't know whether this (moving all the logic to the new callback) would lead to some issues or not, therefore I've decided to leave regular screen behaviour intact for now.
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.
Great!
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.
CI passes locally, here it fails most likely due to slow runner.
Description
This PR relates to new architecture only.
Currently, the pressables on form sheet lose focus on
move
action. This is the same problem we had withPressables
in screen & header on new architecture.See: #2466
Basically the information about sheet position is different between
ShadowTree
(ST) andHostTree
(HT), which leads to losing focus due to how pressablesare now handled on new architecture.
Simplified description of basically what happens when you click a pressable on new arch is as follows (Android):
Therefore, any inconsistency here leads to responder losing focus.
Reference:
TouchesHelper.createPointersArray
What is bewildering is that it works on iOS, despite the fact, that e.g. when using React inspector the views are completely out of place in ShadowTree.
I haven't debugged the iOS part to the very bottom, but my suspicion is as follows:
UITransitionView
(different subtree of window),RNSModalScreen
component on iOS, which has shadow node withRootNodeKind
(measurements in subtree of its shadow node are done relative to it),This is something to verify in the future. Opened ticked on the board for it.
Changes
The sheet now sends updates to the shadow tree at following moments:
I'm not sending updates on every sheet move (
View.top
change), to avoid clogging the JS thread (and later UI), whole advantage of our sheet is that it feels smooth (given sensible Android device).However, it could be considered in case of any further issues.
Please note, that between the event syncs or in case the JS thread is blocked / clogged, this still will be a problem. However, any JS would lag, not only pressables and it's not down to us.
Commits:
headerHeight
to diff prop list when determining need for shadow state updateRecordings
Screen.Recording.2025-03-18.at.14.22.17.mov
Screen.Recording.2025-03-18.at.14.18.08.mov
Test code and steps to reproduce
TestFormSheet
, open the sheet, play with it & see that pressables work!Checklist