From 40f318aaf8833c4b1e3c0b925341522adca5e4c9 Mon Sep 17 00:00:00 2001 From: Evan Bacon Date: Thu, 14 Nov 2024 11:06:03 -0600 Subject: [PATCH] feat: add support for transparent large header on iOS (#2501) ## Description - requires this bug fix https://github.com/software-mansion/react-native-screens/pull/2500 - make it possible to support the stock Apple behavior where the large header is transparent and the collapsed header is blurry with a shadow. This is currently not possible because we inherit the blur effect from the collapsed title, and because there's no way to set the headerLargeTitle blur effect. With this change, the default iOS behavior can more closely be matched by using the following props: ```js { headerLargeTitle: true, headerTransparent: true, headerBlurEffect: "systemChromeMaterial", headerLargeTitleShadowVisible: false, headerShadowVisible: true, headerLargeStyle: { // NEW: Make the large title transparent to match the background. backgroundColor: "transparent", }, } ``` Without the shadow changes, users also need to add this (and adjust for dark mode): ``` { headerStyle: { // Hack to ensure the collapsed small header shows the shadow / border. backgroundColor: "rgba(255,255,255,0.01)", }, } ``` ## Changes ### Before This is the best we can currently do. ![IMG_5976](https://github.com/user-attachments/assets/00d2b4d0-9633-44c1-a038-c311f4e51df1) ### After https://github.com/user-attachments/assets/b1e8999d-14ce-40ef-aef6-2478a9e6326c ## Test code and steps to reproduce ## Checklist - [ ] Included code example that can be used to test this change - [ ] Updated TS types - [ ] Updated documentation: - [ ] 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 --- ios/RNSScreenStackHeaderConfig.mm | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ios/RNSScreenStackHeaderConfig.mm b/ios/RNSScreenStackHeaderConfig.mm index e90564730b..ec31b8b89d 100644 --- a/ios/RNSScreenStackHeaderConfig.mm +++ b/ios/RNSScreenStackHeaderConfig.mm @@ -451,8 +451,16 @@ + (UINavigationBarAppearance *)buildAppearance:(UIViewController *)vc UINavigationBarAppearance *appearance = [UINavigationBarAppearance new]; if (config.backgroundColor && CGColorGetAlpha(config.backgroundColor.CGColor) == 0.) { + // Preserve the shadow properties in case the user wants to show the shadow on scroll. + UIColor *shadowColor = appearance.shadowColor; + UIImage *shadowImage = appearance.shadowImage; // transparent background color [appearance configureWithTransparentBackground]; + + if (!config.hideShadow) { + appearance.shadowColor = shadowColor; + appearance.shadowImage = shadowImage; + } } else { [appearance configureWithOpaqueBackground]; } @@ -680,7 +688,15 @@ + (void)updateViewController:(UIViewController *)vc UINavigationBarAppearance *scrollEdgeAppearance = [[UINavigationBarAppearance alloc] initWithBarAppearance:appearance]; if (config.largeTitleBackgroundColor != nil) { - scrollEdgeAppearance.backgroundColor = config.largeTitleBackgroundColor; + // Add support for using a fully transparent bar when the backgroundColor is set to transparent. + if (CGColorGetAlpha(config.largeTitleBackgroundColor.CGColor) == 0.) { + // This will also remove the background blur effect in the large title which is otherwise inherited from the standard appearance. + [scrollEdgeAppearance configureWithTransparentBackground]; + // This must be set to nil otherwise a default view will be added to the navigation bar background with an opaque background. + scrollEdgeAppearance.backgroundColor = nil; + } else { + scrollEdgeAppearance.backgroundColor = config.largeTitleBackgroundColor; + } } if (config.largeTitleHideShadow) { scrollEdgeAppearance.shadowColor = nil;