-
-
Notifications
You must be signed in to change notification settings - Fork 522
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): back button does not respect I18nManager & improve RTL handling in header #2185
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.
A typo here, and I'll have some remarks to the PR description, so that we describe the whole mechanism in details, so that our debugging hours don't go to waste & we have good starting point for refactoring current header config code.
Regarding the sole logic changes in code - I'm happy with current solution 💪🏻
Co-authored-by: Kacper Kafara <[email protected]>
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.
Let's proceed 💪🏻
…ling in header (#2185) ## Description This PR intents to fix back button direction in RTL mode forced by I18nManager for testing purposes on iOS. When the application's language is changed using the `CFBundleDevelopmentRegion` the system is well aware of that, passes the information to React Native and Yoga. The result is a fully LTR / RTL compliant application. However, when the `RTL` mode is set using the React Native's `I18nManager.forceRTL()` method (for testing purposes I believe) The change is applied to react views only and the system itself does not change it's direction. In such case the only way for the native elements, such as `navigationBar` to adapt to the direction set by `I18nManager` is by manually applying the `semanticContentAttribute` based on `direction` prop passed by `react-navigation`. > [!note] In case there is another native `navigationBar` element apart from the one coming from `react-native-screens`, this change may override it's direction. Tested successfully on iOS 17.5 and 16.4 Fixes #1884 . ## Changes - removed faulty workaround - set correct semanticContentAttribute for navigationBar and it's contents - refactored how the searchbar direction is set ## Screenshots / GIFs ### Before ![image](https://github.com/software-mansion/react-native-screens/assets/91994767/1c67071d-92e4-4966-9ad8-362c54c4435b) ### After ![image](https://github.com/software-mansion/react-native-screens/assets/91994767/5cf40cf1-b762-4720-af33-0f939adac7c5) ## Test code and steps to reproduce - play around with LTR and RTL mode in the example app ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes ## Short story on how RTL management works in RN apps on iOS by @kkafar > [!note] > Basically we have two RTL management systems: native one & ReactNative's I18nManager. > > Native one works most likely by applying semantic content attribute to all the views / classes and impacting layout constraints, thus whole native application is laid out properly. > We can impact RTL on natively managed views by: > * setting semantic content attributes for particular view > * [setting semantic content attributes for particular class through appearance proxy](https://developer.apple.com/documentation/uikit/uiappearance?language=objc) > * [setting semantic content attributes for particular class contained in instances of another class](https://developer.apple.com/documentation/uikit/uiappearance/1615006-appearancewhencontainedin?language=objc) > > Topic's to research: > * how parent's semantic content attribute (set directly on given view) does affect subviews > * exact semantics of using appearance proxy object, their priority and resolve order. > > > React Native has notion of internationalisation manager (I18n) which works as follows: > > * The RTL is allowed by default. > * If RTL is not forced from JS, and allowed, then system language writing direction is resolved based on system calls and such obtained interface direction is passed down to Yoga *impacting all views that are laid out by Yoga*, but not purely native ones such as our header. Thus leading to conformity between system options and RN app options. > * If RTL is forced from JS and allowed, them Yoga managed views are laid out in RTL mode, while system managed ones respect the system settings. > * ForceRTL / AllowRTL flags are stored in `NSUserDefaults` application persistent storage, thus living through application restarts. These flags are RN specific, and system has no knowledge of them. > > React Navigation takes the value from RN I18n system and passes it down to our screen / stack / header components. --------- Co-authored-by: Kacper Kafara <[email protected]> Co-authored-by: Kacper Kafara <[email protected]>
…ling in header (software-mansion#2185) ## Description This PR intents to fix back button direction in RTL mode forced by I18nManager for testing purposes on iOS. When the application's language is changed using the `CFBundleDevelopmentRegion` the system is well aware of that, passes the information to React Native and Yoga. The result is a fully LTR / RTL compliant application. However, when the `RTL` mode is set using the React Native's `I18nManager.forceRTL()` method (for testing purposes I believe) The change is applied to react views only and the system itself does not change it's direction. In such case the only way for the native elements, such as `navigationBar` to adapt to the direction set by `I18nManager` is by manually applying the `semanticContentAttribute` based on `direction` prop passed by `react-navigation`. > [!note] In case there is another native `navigationBar` element apart from the one coming from `react-native-screens`, this change may override it's direction. Tested successfully on iOS 17.5 and 16.4 Fixes software-mansion#1884 . ## Changes - removed faulty workaround - set correct semanticContentAttribute for navigationBar and it's contents - refactored how the searchbar direction is set ## Screenshots / GIFs ### Before ![image](https://github.com/software-mansion/react-native-screens/assets/91994767/1c67071d-92e4-4966-9ad8-362c54c4435b) ### After ![image](https://github.com/software-mansion/react-native-screens/assets/91994767/5cf40cf1-b762-4720-af33-0f939adac7c5) ## Test code and steps to reproduce - play around with LTR and RTL mode in the example app ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: <!-- For adding new props to native-stack --> - [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx - [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx - [ ] Ensured that CI passes ## Short story on how RTL management works in RN apps on iOS by @kkafar > [!note] > Basically we have two RTL management systems: native one & ReactNative's I18nManager. > > Native one works most likely by applying semantic content attribute to all the views / classes and impacting layout constraints, thus whole native application is laid out properly. > We can impact RTL on natively managed views by: > * setting semantic content attributes for particular view > * [setting semantic content attributes for particular class through appearance proxy](https://developer.apple.com/documentation/uikit/uiappearance?language=objc) > * [setting semantic content attributes for particular class contained in instances of another class](https://developer.apple.com/documentation/uikit/uiappearance/1615006-appearancewhencontainedin?language=objc) > > Topic's to research: > * how parent's semantic content attribute (set directly on given view) does affect subviews > * exact semantics of using appearance proxy object, their priority and resolve order. > > > React Native has notion of internationalisation manager (I18n) which works as follows: > > * The RTL is allowed by default. > * If RTL is not forced from JS, and allowed, then system language writing direction is resolved based on system calls and such obtained interface direction is passed down to Yoga *impacting all views that are laid out by Yoga*, but not purely native ones such as our header. Thus leading to conformity between system options and RN app options. > * If RTL is forced from JS and allowed, them Yoga managed views are laid out in RTL mode, while system managed ones respect the system settings. > * ForceRTL / AllowRTL flags are stored in `NSUserDefaults` application persistent storage, thus living through application restarts. These flags are RN specific, and system has no knowledge of them. > > React Navigation takes the value from RN I18n system and passes it down to our screen / stack / header components. --------- Co-authored-by: Kacper Kafara <[email protected]> Co-authored-by: Kacper Kafara <[email protected]>
Description
This PR intents to fix back button direction in RTL mode forced by I18nManager for testing purposes on iOS.
When the application's language is changed using the
CFBundleDevelopmentRegion
the system is well aware of that, passes the information to React Native and Yoga. The result is a fully LTR / RTL compliant application.However, when the
RTL
mode is set using the React Native'sI18nManager.forceRTL()
method (for testing purposes I believe) The change is applied to react views only and the system itself does not change it's direction.In such case the only way for the native elements, such as
navigationBar
to adapt to the direction set byI18nManager
is by manually applying thesemanticContentAttribute
based ondirection
prop passed byreact-navigation
.Note
In case there is another native
navigationBar
element apart from the one coming fromreact-native-screens
, this change may override it's direction.Tested successfully on iOS 17.5 and 16.4
Fixes #1884 .
Changes
Screenshots / GIFs
Before
After
Test code and steps to reproduce
Checklist
Short story on how RTL management works in RN apps on iOS by @kkafar
Note
Basically we have two RTL management systems: native one & ReactNative's I18nManager.
Native one works most likely by applying semantic content attribute to all the views / classes and impacting layout constraints, thus whole native application is laid out properly.
We can impact RTL on natively managed views by:
Topic's to research:
React Native has notion of internationalisation manager (I18n) which works as follows:
NSUserDefaults
application persistent storage, thus living through application restarts. These flags are RN specific, and system has no knowledge of them.React Navigation takes the value from RN I18n system and passes it down to our screen / stack / header components.