Skip to content
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

Fixed scrollview inset when RN view is embedded in another view #27607

Closed
wants to merge 1 commit into from

Conversation

danielgindi
Copy link
Contributor

@danielgindi danielgindi commented Dec 25, 2019

Summary

I'm using RNN, which embeds RN view inside native view controllers.

On iOS 13, a modal view controller is "floating" and is offset from the top of the screen.

This causes the calculation of inset in KeyboardAvoidingView incorrect as it mixes local view controller coordinate space, with keyboard's screen coordinate space.

Changelog

[iOS] [Fixed] - Fixed KeyboardAvoidingView inset in embedded views (i.e modal view controllers on iOS 13)

Test Plan

  1. Tested before and after in a simple view controller (should stay the same)
  2. Tested before and after in a modal view controller (should be offset before, and fixed after)
  3. Repeated no. 2 with each device rotation (upsideDown, landscapeLeft, landscapeRight)

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Dec 25, 2019
Copy link

@analysis-bot analysis-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code analysis results:

  • eslint found some issues. Run yarn lint --fix to automatically fix problems.

Libraries/Components/Keyboard/KeyboardAvoidingView.js Outdated Show resolved Hide resolved
Libraries/Components/Keyboard/KeyboardAvoidingView.js Outdated Show resolved Hide resolved
@danielgindi
Copy link
Contributor Author

Closed by mistake

This happened to me mainly in modal view controllers on iOS 13, where the view controller is floating and does not start from the top.
@analysis-bot
Copy link

Platform Engine Arch Size (bytes) Diff
android hermes arm64-v8a 6,596,711 -8,422
android hermes armeabi-v7a 6,273,863 -7,318
android hermes x86 6,936,846 -8,296
android hermes x86_64 6,866,660 -8,352
android jsc arm64-v8a 8,905,008 -8,462
android jsc armeabi-v7a 8,545,489 -7,372
android jsc x86 8,729,192 -8,340
android jsc x86_64 9,305,222 -8,396

Base commit: 2b062ea

@analysis-bot
Copy link

analysis-bot commented Apr 1, 2020

Platform Engine Arch Size (bytes) Diff
ios - universal 966,896 0

Base commit: 2b062ea

@danielgindi
Copy link
Contributor Author

@kelset This is an easy fix for modals presented in iOS 13, and iOS 14 is almost here....

@kelset
Copy link
Contributor

kelset commented Apr 1, 2020

hey Daniel, thanks for the ping. I can try to put this in front of the right people but can't make promises

Copy link
Member

@elicwhite elicwhite left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change will cause a delay in rendering as the measure is an async round trip to native.

I wonder if this change should be made on the native side and if the layout metrics are wrong for embedded views.

@danielgindi
Copy link
Contributor Author

danielgindi commented Apr 2, 2020

This change will cause a delay in rendering as the measure is an async round trip to native.

I wonder if this change should be made on the native side and if the layout metrics are wrong for embedded views.

I tested in dev and production, there’s no side effects.
The inset is used for when keyboard is visible, which is not the default.
So when the view shows, you calculate the correct position by measuring, not by causing another render. When keyboard shows- you use the precalculated value.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TheSavior has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@elicwhite
Copy link
Member

Ah, alright. That seems reasonable to me.

@react-native-bot
Copy link
Collaborator

This pull request was successfully merged by @danielgindi in fb2900e.

When will my fix make it into a release? | Upcoming Releases

@react-native-bot react-native-bot added the Merged This PR has been merged. label Apr 3, 2020
@elicwhite
Copy link
Member

This needed to be reverted: a37e45a

This caused an issue on the login screen of the Oculus app where the TextInputs were covered up with the login button. Hopefully @xyin96 can provide more info for you to debug and fix this.

@danielgindi
Copy link
Contributor Author

@TheSavior @xyin96 Waiting for more info on this.
Are you sure the inputs weren't covered due to some workaround in the app?

@danielgindi
Copy link
Contributor Author

@TheSavior I don't get it. This got reverted due to a regression in a different app (no matter who stands behind it) without even looking into the bug? Chances are there's a workaround in place because of this bug.

@elicwhite
Copy link
Member

@danielgindi, I totally get where you are coming from. I'm hoping @xyin96 can give more info from the Oculus app so you two can figure out how to proceed.

Fwiw, there being a workaround to this bug that ends up being a problem with this fix is still reason for concern. Who knows how many other surfaces and apps have workarounds for the sad state of the KeyboardAvoidingView. If those screens all break during an upgrade, even if KeyboardAvoidingView is now more correct, it would be detrimental to those companies and apps and make the upgrade more difficult.

I'm hoping that @xyin96 can respond, and a path forward can be found that can make this work better out of the box but also not break existing screens with their current workarounds.

@danielgindi
Copy link
Contributor Author

@TheSavior There is not a single release of RN that does not break a workaround somewhere, or even a valid piece of code. The problem with this issue is that it's actually is very difficult to workaround without glitches and re-rendering.
My "workaround" for RN projects includes a script that runs after npm install and changes some stuff - like migrating some Android imports to androidx. namespace, or applying fixes like the current one.

sasurau4 pushed a commit to sasurau4/react-native that referenced this pull request Apr 15, 2020
…book#27607)

Summary:
I'm using RNN, which embeds RN view inside native view controllers.

On iOS 13, a modal view controller is "floating" and is offset from the top of the screen.

This causes the calculation of inset in `KeyboardAvoidingView` incorrect as it mixes local view controller coordinate space, with keyboard's screen coordinate space.

## Changelog

[iOS] [Fixed] - Fixed `KeyboardAvoidingView` inset in embedded views (i.e modal view controllers on iOS 13)
Pull Request resolved: facebook#27607

Test Plan:
1. Tested before and after in a simple view controller (should stay the same)
2. Tested before and after in a modal view controller (should be offset before, and fixed after)
3. Repeated no. 2 with each device rotation (upsideDown, landscapeLeft, landscapeRight)

Reviewed By: cpojer

Differential Revision: D20812231

Pulled By: TheSavior

fbshipit-source-id: fbd72739fb7152655028730e284ad26ff4a5da73
@xyin96
Copy link

xyin96 commented Apr 15, 2020

Hi @danielgindi, sorry for the late response.

I had begun to look into this a few days back, but got caught up in some other work items. It looks like in our case, the this breaks down because the KeyboardAvoidingView is not our container component.

e.g.:

<SafeAreaView style={{flex: 1}}>
  <KeyboardAvoidingView>
    {/* ... */}
  </KeyboardAvoidingView>
</SafeAreaView>

In this case, if you had tried to measure the layout of the KeyboardAvoidingView, it would have a height of 0.

I'm not too familiar with iOS. But I'm wondering if this fix is better done in the native ViewManager rather than in JS because this would also affect how the component works for Android.

@danielgindi
Copy link
Contributor Author

Sounds weird, as it’s not the root in my case too. And it should not matter as the original code measures its frame relative to the root, not the parent. And the patch does the same, only considering that the root may be offset.
Is it possible though that some scroll offset is getting in the way here in your case?

@danielgindi
Copy link
Contributor Author

@xyin96 Could you please post a sample screen that demonstrates an issue after the fix? I've tested this in all directions, can't see any issue.
Does it even happen on iOS or Android?
Are you using height, padding, or position mode? (on ios padding mode works best for scrollviews in my experience)

@danielgindi
Copy link
Contributor Author

@TheSavior I request for this to be re-merged.

I've tested this thoroughly in every condition imaginable. The offsets always come out right. Wrapped in SafeAreaView, unwrapped, wrapped in ScrollView, unwrapped, with contentInsetAdjustmentBehavior='never' or default, with all behavior modes, inside an iOS 13 modal view controller, inside a normal view controller with navigation bar, without navigation bar, and all possible combinations of all options above.

@elicwhite
Copy link
Member

@xyin96, can you help @danielgindi get a repro for the issue that Oculus had?

I can't remerge this as is. If this gets landed again as is, it would have the same effect. It would break Oculus and Oculus would revert it. It would require me getting familiar with the Oculus app and getting a repro for you myself which I don't have the bandwidth for, so I'm hoping that @xyin96 can help. I recognize this is unfortunate and doesn't leave you with an easy way to move forward. :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. Component: ScrollView Merged This PR has been merged. Platform: iOS iOS applications.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants