25

I am using nativebase.io as the UI framework for my app.

My issue

when I input a header for an IOS device, if the iPhone simulator is simulating iPhone X, (where there is a notch on the top of the screen), the Header element automatically detects this and moves the Header element lower on the screen.

some android devices also have a similar notch at the top of the screen, but when I use a nativebase.io Header element, it doesn't detect the notch and the Header overlaps the notch.

My question

is there a way on react-native or nativebase.io to detect if the display has a notch? this way I could dynamically offset the Header.

Umang Loriya
  • 643
  • 6
  • 14
X0r0N
  • 1,306
  • 3
  • 18
  • 42
  • I think NativeBase should implement it on their own replacement will be try using SafeAreaView from react-native. – Ashwin Mothilal Aug 15 '18 at 13:03
  • thank for your reply. SafeAreaView does not work on android. on the official documentation, it also says [It is currently only applicable to iOS devices.](https://facebook.github.io/react-native/docs/safeareaview.html) – X0r0N Aug 15 '18 at 13:33
  • Thank you, I think then this will help for you - https://developer.android.com/reference/android/view/WindowInsets#getStableInsetTop() I mean, use this api to write react api and use it in JS methods. – Ashwin Mothilal Aug 15 '18 at 13:55
  • Can you tell the Android device that you are trying in this case – Supriya Kalghatgi Aug 20 '18 at 05:12
  • @SupriyaKalghatgi i am developing using OnePlus 6 – X0r0N Aug 20 '18 at 06:09

5 Answers5

19

Since the problem is on android, maybe you should try looking into StatusBar.currentHeight. Since the notch generally is part of the status bar, adding a padding on top of the header the size of the status bar should probably do it.

Filipe
  • 811
  • 5
  • 12
  • 3
    Thanks! this works. to be more specific about the solution, i used `
    `. the documentation can be [HERE](https://facebook.github.io/react-native/docs/statusbar.html)
    – X0r0N Aug 15 '18 at 14:49
  • 3
    It doesn't work if we hide `StatusBar`. That's need to know the device has notch or not to display top padding – TomSawyer Aug 21 '18 at 08:45
  • @TomSawyer I believe then it is not possible to know it, since it's native that calculates status bar height. If you use case needs it completely black/white, using ```backgroundColor="black"``` with ```barStyle="dark-content"``` or similar for white will do it. However, if you want to show content in that space, you'll either have to show the statusBar for a brief moment, calculate its height, and then save it and hide the bar, or customize native code. – Filipe Aug 21 '18 at 12:12
15

Not Using Expo

If you are using React Native without Expo, or an Expo app which has been ejected, you can use the react-native-device-info package. It has a hasNotch() function which works pretty well at detecting such devices.

The Native Base Content, Footer and Header components inspect an isIphoneX theme variable to determine whether or not to add spacing for a device notch.

You can customized your Native Base theme and modify your variables files to use react-native-device-info to detect the notch:

# native-base-theme/variables/*.js
import DeviceInfo from 'react-native-device-info';
...
isIphoneX = DeviceInfo.hasNotch();
...

Now your Native Base Header, Footer and Content components should add the appropriate spacing for devices that have notches.

Using Expo

Since react-native-device-info does not work on Expo projects, there is not a simple way to do this. You will have to write a function to accomplish your goal. If you inspect the hasNotch() source code, you will notice that the function simply does an array lookup based on the device's brand and model. You can get the device model using Expo Constants, but they do not make it easy:

import { Platform } from 'react-native;
import Constants from 'expo-constants';

const getDeviceModel = () => Platform.select({
  ios: Constants.platform.ios.model,
  android: Constants.deviceName
});

However, there is no way to get the device brand in Expo. Obviously, all ios devices have a brand of Apple, but the Android device brands are more elusive. You may be able to construct a lookup array that only uses the device model, but it may not be as accurate.

I wish there were a better solution for Expo users.

Tom Aranda
  • 4,698
  • 10
  • 29
  • 45
  • 2
    You can access the StatusBar.currentHeight if Android through React Native regardless of Expo (and the height of the notch is detected). No need for this solution. If iOS, your solution is helpful, and the brand name is easy :) – colemerrick Jul 31 '19 at 01:47
  • Actually, in iOS >= 11, you can use SafeAreaView. For older iOS, the phones most likely don't have notches, so you're good with a fixed top margin. – colemerrick Jul 31 '19 at 02:01
  • isIphoneX from native-base what worked for me. I add margin for Android with a value of StatusBar.currentHeight and 20px for iOS that has no notch. For those iOS with notch, keep at 0 margin. Thx for this response, helped a lot! – Symyon Mar 20 '20 at 16:28
  • 1
    FYI there are Android devices with a notch. The Huawei P20 comes to mind https://www.gsmarena.com/huawei_p20-9107.php , so `isIphoneX` is incorrectly named. – Sandy Feb 15 '21 at 19:33
  • @Sandy, true, but that is the the variable name Native Base uses (or at least the variable they used when this post was written). – Tom Aranda Feb 16 '21 at 18:11
13

I'm using the approach from this answer https://stackoverflow.com/a/53593067/923497 and it is working fine for me.

In React Native looks like

import { StatusBar, Platform } from 'react-native';

if (Platform.OS === 'android') {
  const hasNotch = StatusBar.currentHeight > 24;
}
Dima Portenko
  • 2,344
  • 21
  • 40
  • This does not work on Moto G8+ – msmfsd Mar 24 '21 at 01:29
  • @msmfsd unfortunately, I don't think there is a universal solution that works for all existing devices. So what I'm doing in my projects I use solutions from the answer and hardcode phone models which are exceptions. – Dima Portenko Mar 24 '21 at 12:33
2

Safe Area View is the way go to.

The purpose of SafeAreaView is to render content within the safe area boundaries of a device. It is currently only applicable to iOS devices with iOS version 11 or later.

https://reactnative.dev/docs/safeareaview

Andrew
  • 2,092
  • 4
  • 24
  • 44
1

I have been using this library "react-native-status-bar-height" and works pretty good.

https://www.npmjs.com/package/react-native-status-bar-height