React Native status bar (Android immersive)

In a real project, we often need to modify the status bar of performance based on a different page. For example: the page header image extends to the lower bar and the status bar a transparent state; the same color and the color of the title bar of the status bar; the contents of the status bar shades of color. Before that, I wrote an article React Navigation building Android and iOS unified UI article, which comes to some simple settings Android status bar. Later I found out I was not thinking so simple, so this blog supplemented by more detailed description of the status bar text will be relevant content as well React Native project in the status bar to control how the application on iOS and Android platforms It has a good performance.

The sample code I uploaded to GitHub: github.com/hezhii/rn_s...

Preliminaries

Before the official start, let me introduce some of my current understanding of knowledge down, some foreshadowing for the following content.

iOS status bar

In iOS, the default page full screen (status bar does not occupy space), the status bar by default content is dark. Because full-screen page, so if we do not deal with the content will go to the status bar below. At the same time, the emergence of iPhone X and other fringe-screen phone, resulting in a high degree the status bar has changed from the previous  20 become  34. To solve this problem, we can manually set the assembly to the top  paddingTop(the value determined in accordance with the model), or use  SafeAreaView components.

In iOS we only deal with the security issues of the region, and then to set the color depth can be, depending on the content of the page.

Android status bar

In Android, the default page non-full screen (status bar occupy space), the status bar by default content is light .

Support for the Android status bar has gone through several versions:

  • Android4.4 (the API. 19) the Android ~ 5.0 (21 is the API) : by  FLAG_TRANSLUCENT_STATUS setting the page to full screen and the status bar translucent (light gray).

  • 5.0 android (21 is the API) : provides  android:statusBarColor properties and  setStatusBarColormethods used to set the color of the status bar.

  • 6.0 Android (API 23) : By  SYSTEM_UI_FLAG_LIGHT_STATUS_BAR support setting status bar content is dark.

Among them, if you want to set the status bar color can not be set  FLAG_TRANSLUCENT_STATUS.

In the Android application, each Activity corresponds to a status bar. This means that the status bar is set to a page does not affect the status bar to other pages.

React Native status bar

React Native official of the  StatusBar components used to control the status bar, set up to support the contents of the depth of color, status bar background (Android) and the like.

StatusBar Can add multiple simultaneously, the attribute is combined (the latter over the former) in accordance with the loading order.

Unlike Android status bar, the status bar React Native is common, anywhere modify status bar will result in a change in the status bar, even if the page is not switched to the other set. Therefore, we need each page rendering are set at the corresponding status bar, or in the left set up the page to reset the status bar status bar.

actual case

In the understanding of the necessary knowledge, let's look at what we need to do and how to do it better by an actual case.

In this case, there are three pages: Home, My login. The "Home" and "I" are two tabs, "Home," the head of the background picture, "my" top of the page is blue, the top of the "login" page is white. Page results as FIG.

"Home" and "my" pages use a custom Header, the component will be based on the current device, obtain the height of the status bar:

const STATUS_BAR_HEIGHT = isiOS() ? (isiPhoneX() ? 34 : 20) : StatusBar.currentHeight
复制代码

Wherein the device is determined using the following method:

// iPhone X、iPhone XS
const X_WIDTH = 375;
const X_HEIGHT = 812;

// iPhone XR、iPhone XS Max
const XSMAX_WIDTH = 414;
const XSMAX_HEIGHT = 896;

const DEVICE_SIZE = Dimensions.get('window');
const { height: D_HEIGHT, width: D_WIDTH } = DEVICE_SIZE;

export const isiOS = () => Platform.OS === 'ios'

export const isiPhoneX = () => {
  return (
    isiOS() &&
    ((D_HEIGHT === X_HEIGHT && D_WIDTH === X_WIDTH) ||
      (D_HEIGHT === X_WIDTH && D_WIDTH === X_HEIGHT)) ||
    ((D_HEIGHT === XSMAX_HEIGHT && D_WIDTH === XSMAX_WIDTH) ||
      (D_HEIGHT === XSMAX_WIDTH && D_WIDTH === XSMAX_HEIGHT))
  );
};
复制代码

After obtaining the height of the status bar, the current is not full screen ( fullSreen property  true or iOS device) to set up their own height and  paddingToptitle bar height is set to unity 44.

const headerStyle = [
  styles.header,
  (fullScreen || isiOS()) && {
    height: STATUS_BAR_HEIGHT + HEADER_HEIGHT,
    paddingTop: STATUS_BAR_HEIGHT
  }
]
复制代码

Header "Login" page is  react-navigation the default  Header component in Android in the title bar height is set  56.

Deal with the problem of the status bar

From the case in the figure above, the following problems can be found:

  • iOS devices, the status bar color display content is not correct, the "Home" and "my" page status bar should be light-colored.

  • Android devices, "home" in the status bar should be transparent, and the picture should be extended to the lower status bar.

  • Android devices, "my" page status bar color should also be blue.

In order for the application to perform better, according to the page we need to dynamically adjust the status bar. React Native provided StatusBar component for developers to control the status bar.

StatusBar component controls the status bar

We in the "Home", set the status bar reads "light", the background color is transparent, translucent is  true. Then, the "Home" and Header "my" pages are added  fullScreen attributes. Results are as follows:

Can be seen from the figure, because the page is js layer routing done, the entire application corresponds to one  StatusBar, although the "I" and "log in" page not set the status bar, but the status bar is also transparent.

So there is a problem, "Login" page can actually use the default results, but due to other pages set the status bar, leading into the "Login" page when the effect is not right. So, each page should set the corresponding status bar, status bar may be altered because of other pages.

Next, in the "Login" page set the status bar is white and dark content:

<StatusBar translucent={false} backgroundColor='#fff' barStyle="dark-content" />
复制代码

Now the effect of the "Login" page on and expect the same, and when we return from the "Login" page to the main screen, the status bar will switch back to the previous state, but there is a little delay. According to previous experience, when coming back from the login page, the status bar should still be white and dark content. Since returning, the front page will not re-rendering, the status bar should be to maintain the current status. However, the status bar automatically adjusts the state before it became, although there is a little delay. I react- navigation find someone mentioned GitHub issue, when to leave  route, it will automatically reset the status bar. I do not have specific studies, but I agree with that, it must be somewhere to do such a deal.

So why is there a delay it? I guess this should be the time to automatically reset the status bar of lead. I try to add a registration page (click the button to enter the login page), and set the status bar is red. Then I listen for the login page  willFocus and  didFocus events, respectively, in the event handler, the status bar is set to white. As a result, in  willFocus the process it is what we expect results, and  didFocus when no default processing and handling is the same.

Here, we can draw a basic conclusion: if we want to adjust the status bar in the app, the prudent approach is to a page in each  willFocus set their respective state bar, the front page unless it can ensure a status bar itself and the same .

Because this feature is very common, so we can get this done by a high-level components:

export const setStatusBar = (statusbarProps = {}) => WrappedComponent => {
  class Component extends React.PureComponent {
    constructor(props) {
      super(props)
      this._navListener = props.navigation.addListener('willFocus', this._setStatusBar)
    }

    componentWillUnmount() {
      this._navListener.remove();
    }

    _setStatusBar = () => {
      const {
        barStyle = "dark-content",
        backgroundColor = '#fff',
        translucent = false
      } = statusbarProps
      StatusBar.setBarStyle(barStyle)
      if (isAndroid()) {
        StatusBar.setTranslucent(translucent)
        StatusBar.setBackgroundColor(backgroundColor);
      }
    }

    render() {
      return <WrappedComponent {...this.props} />
    }
  }

  return hoistNonReactStatics(Component, WrappedComponent);
}
复制代码

By using the decorator way is also very simple:

@setStatusBar({
  barStyle: 'light-content',
  translucent: true,
  backgroundColor: 'transparent'
})
export default class Home extends React.PureComponent {
 ... 
}

复制代码
Android status bar and set the full-screen transparent

In addition to js layer by  StatusBar the state assembly set the status bar color, translucent and so on, we can first Android column to full screen and status bar transparent, so that the performance on Android and iOS, as can be unified to deal with.

In  MainActivity.java adding the following code, the status bar may be provided full screen and transparent:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    View decorView = getWindow().getDecorView();
    decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
    if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setStatusBarColor(Color.TRANSPARENT);
    }
}
复制代码

After completion effect provided below (no treatment  paddingTop).

Now show the status bar on Android and iOS same, when treated in accordance with the unified processing logic to iOS, but in the Header and height of  paddingTop the different computing.

In addition, also need to pay attention to  react-native is  Header not the case handle full-screen Android, so we need to modify the Android platform  headerStyle:

defaultNavigationOptions: {
  headerStyle: {
    ...Platform.OS === 'android' && {
      height: StatusBar.currentHeight + 44,
      paddingTop: StatusBar.currentHeight
    }
  }
}
复制代码
to sum up

React Native want to make in the status bar to perform better still need to do some work. It now appears that in fact the use of  StatusBar components more easily, because even in the Android native level and set up a full-screen transparent status bar, in the end need to set the color of the status bar according to the page content, so it is not allowed to do in js uniform layer, by way high-order component is not very troublesome.

Reproduced in: https: //juejin.im/post/5cf4c495f265da1ba647d687

Guess you like

Origin blog.csdn.net/weixin_34111790/article/details/91469513