-
-
Notifications
You must be signed in to change notification settings - Fork 530
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(iOS): modal view flickering #1870
fix(iOS): modal view flickering #1870
Conversation
Is the current code safe to use as a patch? |
Hey, I just added Bottom Sheet support to my Navigation router on iOS. I removed the flicker you're seeing when the sheet is dropped. Details in the PR but let me know if you want to know more |
Hey @grahammendick, great to hear that you've managed to find a solution to this. I took a look at your PR description and code and my understanding of your solution is as follows:
Is that correct & full picture? What worries me is that calling My approach was to reject frame updates coming from React during animation, but this led to "modal content jumping after the animation finish"... Thank you for sharing your solution with us! |
Yea, that's almost the full picture. I don't think the invalid values come from So, the solution is to ignore |
d1fc618
to
3ba3d43
Compare
2de9953
to
c0b445b
Compare
## Description Should be merged to #1852 or first rebased and then merged to main after #1852. Closes #1722 So the exact roots of the issue are unclear & obfuscated. It seems that it might be related to following (not 100% sure): 1. It looks like during animation `viewDidLayoutSubviews` is being called which in turn calls `setSize:forView:` on UIManager. This triggers Yoga layout underneath which sets view dimensions to the target values (end animation values) resulting in view clipping during the animation. There are two more important facts: a. its hard to determine whether its Yoga who sets invalid value or it gets invalid value from us (passed in `updateBounds` method after `viewDidLayoutSubviews` is triggered by system. b. when uimanager is not notified of bounds size change everything works fine I've considered various approaches: 1. Do not pass the value to UIManager when animation is ongoing. Presence of animation was detected by checking `animationKeys` property of view's layer. This still resulted in visual glitches. Moreover if I sent the final value after animation finish (via completion block) it resulted in content jumping (see [here](facebook/react-native#34834 (comment))). 2. Use `CADisplayLink` & report to UIManager bounds size from `presentationLayer` (that should be (almost) accurate value), but it still resulted in visual glitches (even when sliding down), both flickering and content jumping or just content had wrong top offset / padding. 3. Do not notify UIManager at all on bounds change. ## Changes I went with this approach for now. That is: I do not notify uimanager on bounds change when `stackPresentation == formSheet`. This is wild I know. I experimented a bit trying to find out what did it broke, but I did not find anything on my toy example (Test1649), however it is highly unlikely that such approach does not have negative impact, but I believe it is better that way, than having formsheets unusable due to this flickering. ## Test code and steps to reproduce Test1649 ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes
Description
Should be merged to #1852 or first rebased and then merged to main after #1852.
Closes #1722
So the exact roots of the issue are unclear & obfuscated. It seems that it might be related to following (not 100% sure):
It looks like during animation
viewDidLayoutSubviews
is being called which in turn callssetSize:forView:
on UIManager. This triggers Yoga layout underneath which sets view dimensions to the target values (end animation values) resulting in view clipping during the animation. There are two more important facts:a. its hard to determine whether its Yoga who sets invalid value or it gets invalid value from us (passed in
updateBounds
method afterviewDidLayoutSubviews
is triggered by system.b. when uimanager is not notified of bounds size change everything works fine
I've considered various approaches:
animationKeys
property of view's layer. This still resulted in visual glitches. Moreover if I sent the final value after animation finish (via completion block) it resulted in content jumping (see here).CADisplayLink
& report to UIManager bounds size frompresentationLayer
(that should be (almost) accurate value), but it still resulted in visual glitches (even when sliding down), both flickering and content jumping or just content had wrong top offset / padding.Changes
I went with this approach for now. That is: I do not notify uimanager on bounds change when
stackPresentation == formSheet
. This is wild I know. I experimented a bit trying to find out what did it broke, but I did not find anything on my toy example (Test1649), however it is highly unlikely that such approach does not have negative impact, but I believe it is better that way, than having formsheets unusable due to this flickering.Test code and steps to reproduce
Test1649
Checklist