Open brentvatne opened 6 years ago
Now that we have focus and blur events, it shouldn't be very hard to build an HOC which can manage status bar automatically.
I was picturing something like this in the screen navigationOptions
:
DarkModeScreen.navigationOptions = ({ navigation }) => ({
statusBarStyle: navigation.params.darkMode ? 'light' : 'default',
statusBarVisible: true,
title: 'Im a screen with toggleable dark mode',
// I'm not sure if this is a thing yet, but it would also be handy:
headerColor: navigation.params.darkMode ? 'black' : undefined,
});
@brentvatne, is this the sort of thing you had in mind? I'm not sure how the API would look like with a HOC.
Exactly @ericvicenti. I think this is important enough that it's worth building into navigationOptions
. We probably need to expose a couple more options -- for animation type and color 😅 (Android gives more control over color than just light/dark)
With Screen
being a component, this could be as easy as allowing statusBar
prop to receive an instance of StatusBar
.
What is the status of this, sounds a simple fix?
like most things it's much more complex than it seems like on the surface. if anyone wants to work on this i can fill you in on the nuances and we can talk through them
Not sure if this is correct place to comment about Status bar different solutions. Please pardon if not correct place. We also faced this issue in our app. We tried following options:
<StatusBar barStyle="light-content" backgroundColor="red">
inside render()
method. But there were some component that did not re-render when we came back to a screen. So users were stuck with wrong status bar color. Then we added navigation as prop so that navigation prop changes to trigger render and removed our scu
optimization for those components that did not render.<CustomHeader />
component (extending ReactNavigation's header) that used to take header's background color, and then set StatusBar background color. For barStyle, we used npm package color
, and used Color(headerColor).isLight() ? "dark-content" : "light-content"
, and then added memoization on top of this function. It worked fine for most screens, but there were few screens that did not have Header at all and for those we used to resort to a hack that works on each screen separately.onNavigationStateChange
and then call updateStatusBar
function on the basis of routeName currently active. This allowed us to handle many scenarios. But people used to forget to update status bar color, route name to status bar mapping, adding new routes needs to be changed at different place than that screen or that particular screen file. Since these files were different, changing color of Header did not change color of status bar. We even added a checklist in our PR template so that developers don't forget it, but even then there were cases where status bar color would be different. One common case that Status bar background color would be #F7F7F7
, and header color would be white. So, normally developers didn't notice something different.withStatusBar()
. And while exporting a screen for react navigation navigator, we wrap screen with this HOC. Some sample uses.
withStatusBar()(connect(mapStateToProps)(About))
...
withStatusBar({color: headerColor})(connect(mapStateToProps)(About))
Inside this HOC, we are using didFocus events, and not isFocused
prop. It works for all our cases.
For this RFC, Nice thing about defining status bar in navigation options is that we can define a default status bar color that works for most of screens in top level navigator, and then whichever screen/route needs a new status bar color, that can also be customized using navigation options of that screen. One thing that we need to ensure with navigation options is that on every route change we should set status bar color by picking it up from screen's navigation options or default options because one screen can change status bar color to white, and previous route might need red color when we goBack() or we need to set default color again.
There is one use case in my mind that can't be handled with static navigation options. If a screen needs to change status bar color dynamically, then there is no way to set dynamic color and re-render/set status bar color and style. Example of dynamic status bar color is that same screen/route is used to render different friends's profile, and developer might want to choose a color from image or some screen is used to show info for different fruits and developer might want to match status bar with fruit color. It might be that there is a way to change dynamic status bar color from static navigation options and I don't know about it. Our solution #1 handles this scenario, but our HOC can't handle this scenario. HOC in general can't handle this scenario unless developers lift the status bar color state to a prop that can trigger a re-render to HOC and change status bar color, which, I am not sure if all developers would like to do.
In my opinion, React hooks can handle dynamic status bar and attaching to events like didFocus without component re-rendering. But, one problem that hooks and HOC share is that we have to import it in every screen of an app and then call them. With navigation options, defining defaults is pretty easy and only for those screens that needs something different, developers can import a hook useStatusBar
exposed by react navigation. Now, we might think that a combination of navigation options with a hook could solve most of the use cases and issues with Status Bar. But, there is one issue that I forsee in combination approach. If we are using both navigation options for default config and a hook inside render method, then we need to ensure that react navigation's Status Bar config options code runs before render method of screen component, because screen component status bar calls takes precedence on navigation options.
If we can ensure the order of execution for setting status bar color and style, then I think a combination of default navigation options along with useStatusBar
hook, we should handle almost all cases of handling status bar with react navigation.
If we have a way to handle dynamic status bar with static navigation options, then I think we won't need a React hook and just navigations options should be able to handle most use cases.
Once we finalize on rfc, I can work on creating a PR that adds support for it, If no one is already working on it. But this is my first time contributing to react navigation (or any open source project) so it might take more time than others who are familiar with it.
Any update on this?
via @dantman in https://github.com/react-navigation/react-navigation/issues/11
Related feature request: https://react-navigation.canny.io/feature-requests/p/control-statusbar-config-for-screens-in-navigationoptions