-
-
Notifications
You must be signed in to change notification settings - Fork 537
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
Header back button does not shorten to 'Back' on iOS if there's not enough space #1589
Comments
After a whole afternoon of investigation I have found the issue. There is a system issue where the back button does not change to "Back" if the navigation item's Even if there is no I have found that this is only caused when I use I think we can still take a look at keeping this behavior if the style is changed. We may want to look at using UINavigationBarAppearance for iOS 13.0 and newer to change the style of the back button. With the following snippet I was able change the font of the back button while maintaining system behavior: NSMutableDictionary *attrs = [NSMutableDictionary new];
attrs[NSFontAttributeName] = [UIFont fontWithName:@"AvenirNextCondensed-DemiBoldItalic" size:17];
UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
appearance.backButtonAppearance.normal.titleTextAttributes = attrs;
navctr.navigationBar.scrollEdgeAppearance = appearance;
navctr.navigationBar.standardAppearance = appearance; We'd probably want to combine something like that to lines 505-518. Not sure if there's a solution for this for versions before iOS 13.0 or when the long press menu needs to be disabled. I'd be happy to submit a PR but I wanted to discuss this a little first. |
Unfortunately the changes from react-navigation#10761 caused an issue I reported on the react-native-screens repo. (See software-mansion/react-native-screens#1589) Essentially, the documentation states that per native behavior, the back button on iOS will automatically use the title of the previous screen or "Back" if there's not enough space. However, with the latest version of react-navigation, the back button was the title of the previous screen no matter what. In some cases, this caused the title of the current screen to be completely pushed off the screen. In UIKit this happens when the title of the back button is deliberately set, or when a custom UIBarButtonItem is set as the back button. `react-native-screens` creates a custom UIBarButtonItem when the header config component has a value defined for `headerBackTitle`. So by leaving headerBackTitle undefined here, we let the system automatically determine what to set as the back button title. In my testing, system will choose the correct value even if the previous screen's `title` or `headerTitle` is set differently from the route name.
Unfortunately the changes from #10761 caused an issue I reported on the react-native-screens repo. (See software-mansion/react-native-screens#1589) Essentially, the documentation states that per native behavior, the back button on iOS will automatically use the title of the previous screen or "Back" if there's not enough space. However, with the latest version of react-navigation, the back button was the title of the previous screen no matter what. In some cases, this caused the title of the current screen to be completely pushed off the screen. In UIKit this happens when the title of the back button is deliberately set, or when a custom UIBarButtonItem is set as the back button. `react-native-screens` creates a custom UIBarButtonItem when the header config component has a value defined for `headerBackTitle`. So by leaving headerBackTitle undefined here, we let the system automatically determine what to set as the back button title. In my testing, system will choose the correct value even if the previous screen's `title` or `headerTitle` is set differently from the route name.
Previously if a custom font or font size was set in the config, a new `RNSUIBarButtonItem` would be created and set as the back bar button item. However, this would break native behavior where the button title would shorten to "Back" if there's not enough space. In iOS 13 it's possible to keep this native behavior and also style the back button using `UINavigationBarAppearance`. The only caveat with this approach is that because `UINavigationBarAppearance` is not available prior to iOS 13, so on older systems we will go ahead and create a custom `RNSUIBarButtonItem`. This solves some issues mentioned in software-mansion#1589.
This bug is (still) fixed in v3.20, but it breaks again in v3.21 and newer. I have provided a repro here: https://github.com/h-five-e/repro-navigation-Ios-back-button-shows-long-title |
I did some experimentation, and it seems this issue still exists with I tested a few more versions and can confirm that it's working on v3.20 but broken in v3.21 and newer as @h-five-e stated, and the issue is still valid on 3.31.0-rc.1 even with
|
After some investigation of the code, I think the cause is that in v3.21, the As the desired behavior can be restored with this patch: diff --git a/ios/RNSScreenStackHeaderConfig.mm b/ios/RNSScreenStackHeaderConfig.mm
index f7ec74678166f485a58ff3b8053a63befad14cfe..92adfb2874e027686c9bea82e5107c568bf5816f 100644
--- a/ios/RNSScreenStackHeaderConfig.mm
+++ b/ios/RNSScreenStackHeaderConfig.mm
@@ -511,8 +511,13 @@ namespace react = facebook::react;
action:nil];
[backBarButtonItem setMenuHidden:config.disableBackButtonMenu];
+ auto isBackButtonCustomized = !isBackTitleBlank || config.disableBackButtonMenu || NO;
+
if (config.isBackTitleVisible) {
- if (config.backTitleFontFamily || config.backTitleFontSize) {
+ if ((config.backTitleFontFamily &&
+ ![config.backTitleFontFamily isEqual:@"System"]) ||
+ config.backTitleFontSize) {
+ isBackButtonCustomized = YES;
NSMutableDictionary *attrs = [NSMutableDictionary new];
NSNumber *size = config.backTitleFontSize ?: @17;
if (config.backTitleFontFamily) {
@@ -535,9 +540,17 @@ namespace react = facebook::react;
// When backBarButtonItem's title is null, back menu will use value
// of backButtonTitle
[backBarButtonItem setTitle:nil];
+ isBackButtonCustomized = YES;
prevItem.backButtonTitle = resolvedBackTitle;
}
- prevItem.backBarButtonItem = backBarButtonItem;
+
+ // Prevent unnecessary assignment of backBarButtonItem if it is not customized,
+ // as assigning one will override the native behavior of automatically shortening
+ // the title to "Back" or hide the back title if there's not enough space.
+ // See: https://github.com/software-mansion/react-native-screens/issues/1589
+ if (isBackButtonCustomized) {
+ prevItem.backBarButtonItem = backBarButtonItem;
+ }
if (@available(iOS 11.0, *)) {
if (config.largeTitle) { |
#2105) ## Description Restore the iOS native behavior of automatically shorting the title of the header back button to "Back" if there is not enough space, which is documented [here](https://reactnavigation.org/docs/header-buttons#customizing-the-back-button)[^1] but does not behave as expected since v3.21. Fixes #1589. ## Changes * Assign to `backBarButtonItem` only if actual customizations of the back button are being made. ## Screenshots / GIFs | Before | After | |--------|------| | ![Broken 1](https://github.com/software-mansion/react-native-screens/assets/3784687/880eaecb-54d9-48d3-95bd-5f8e6cd7b066) | ![Working 1](https://github.com/software-mansion/react-native-screens/assets/3784687/201e8006-544d-43ee-95e3-308e2f926566) | ## Test code and steps to reproduce <!-- Please include code that can be used to test this change and short description how this example should work. This snippet should be as minimal as possible and ready to be pasted into editor (don't exclude exports or remove "not important" parts of reproduction example) --> ## 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 [^1]: According to the document, 'On iOS this includes a label next to the button, which shows the title of the previous screen when the title fits in the available space, otherwise it says "Back".' --------- Co-authored-by: Kacper Kafara <[email protected]>
- Fixes: Title truncated on NewNominationScreen by long back button title instead of "Back" - Introduced during the RN73 upgrade - software-mansion/react-native-screens#1589 - software-mansion/react-native-screens#2105 - https://github.com/software-mansion/react-native-screens/releases/tag/3.32.0
- Fixes: Title truncated on NewNominationScreen by long back button title instead of "Back" - Introduced during the RN73 upgrade - software-mansion/react-native-screens#1589 - software-mansion/react-native-screens#2105 - https://github.com/software-mansion/react-native-screens/releases/tag/3.32.0
Hey! Great that this problem is solved, but is there a way to override/make sure that the back text even show's if that results in shortening? |
@JustJoostNL could you describe a bit more expressively what case exactly do you mean here? |
@kkafar In my app, I always want the back text to show (the title of the previous page) whether it fits or not. |
I don't think this is possible right now, after changes from #2105 were applied. It was considered as breaking the native behaviour and we decided to go against it. This is not the way iOS implements this & the idea of native header is to follow iOS beahavior here. You can try experimenting with disabling back button & putting your custom header left there or implement whole custom header. |
software-mansion#2105) ## Description Restore the iOS native behavior of automatically shorting the title of the header back button to "Back" if there is not enough space, which is documented [here](https://reactnavigation.org/docs/header-buttons#customizing-the-back-button)[^1] but does not behave as expected since v3.21. Fixes software-mansion#1589. ## Changes * Assign to `backBarButtonItem` only if actual customizations of the back button are being made. ## Screenshots / GIFs | Before | After | |--------|------| | ![Broken 1](https://github.com/software-mansion/react-native-screens/assets/3784687/880eaecb-54d9-48d3-95bd-5f8e6cd7b066) | ![Working 1](https://github.com/software-mansion/react-native-screens/assets/3784687/201e8006-544d-43ee-95e3-308e2f926566) | ## Test code and steps to reproduce <!-- Please include code that can be used to test this change and short description how this example should work. This snippet should be as minimal as possible and ready to be pasted into editor (don't exclude exports or remove "not important" parts of reproduction example) --> ## 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 [^1]: According to the document, 'On iOS this includes a label next to the button, which shows the title of the previous screen when the title fits in the available space, otherwise it says "Back".' --------- Co-authored-by: Kacper Kafara <[email protected]>
Description
According to the documentation, the back button title is supposed to change to "Back" if there's not enough space for the full title of the previous screen. That is not what I'm experiencing. In the GIF below you can see that instead of changing to "Back" it will truncate the header title, and if it's long enough, the back button will use the entire header width, hiding the title.
Steps to reproduce
Snack or a link to a repository
https://github.com/DrOverbuild/BackButtonRepro
Screens version
3.17.0
React Native version
0.70.0
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native (without Expo)
Architecture
Paper (Old Architecture)
Build type
Debug mode
Device
iOS simulator
Device model
iPhone 13 (iOS 15.5)
Acknowledgements
Yes
The text was updated successfully, but these errors were encountered: