React Native doesn't have a direct way to reliably know whether a device has a notch, dynamic island, or neither. So, here's how I solved it…
Background story
A few weeks ago I was working on the company's app, specifically on the UI section. So, if you're a React Native developer working on your app's frontend, at some point you'll come across a particular feature of certain devices where, for your frontend to adapt efficiently, you'll need to detect whether the device in question has a notch or dynamic island.
React native Gap
At least, until a few weeks ago when I tried to accurately detect the notch on some devices, it didn't work well. Let's remember that this might be easily covered on iPhone, since the models maintain consistency across different versions; however, on Android things are more chaotic, since, as you may know, each manufacturer does whatever it wants with Android according to its own ideas and needs.
Implementation
Let's get to work: how could we more accurately determine whether a device has a dynamic island or notch or not? By following these steps.
Android
To detect on Android whether the device has this particular feature, we're going to create a file at the following location:
android > app > src > main > java > com > [name of your app] > NotchDetectorPackage.java
package com.[name of your app];
package com.[name of your app];
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.*;
import com.facebook.react.uimanager.ViewManager;
import java.util.*;
public class NotchDetectorPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext rc) {
return Arrays.asList(new NotchDetectorModule(rc));
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext rc) {
return Collections.emptyList();
}
}
MainApplication.kt:
import com.[name of your app].NotchDetectorPackage
class MainApplication : Application(), ReactApplication {
override val reactNativeHost: ReactNativeHost =
object : DefaultReactNativeHost(this) {
override fun getPackages(): List<ReactPackage> =
PackageList(this).packages.apply {
add(NotchDetectorPackage())
}
....
IOS
For iOS devices, we're going to create two files in the following location in the project: ios > NotchDetector.h
#import <React/RCTBridgeModule.h>
@interface NotchDetector : NSObject <RCTBridgeModule>
@end
And too: ios> NotchDetector.m
#import "NotchDetector.h"
#import <UIKit/UIKit.h>
@implementation NotchDetector
RCT_EXPORT_MODULE();
RCT_REMAP_METHOD(hasNotch, resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
@try {
UIWindow *window = UIApplication.sharedApplication.windows.firstObject;
if (!window) {
NSLog(@"[NotchDetector] No window found");
resolve(@(NO));
return;
}
CGFloat top = window.safeAreaInsets.top;
NSLog(@"[NotchDetector] top safeAreaInset: %f", top);
resolve(@(top > 20));
} @catch (NSException *exception) {
NSLog(@"[NotchDetector] Exception: %@", exception);
reject(@"error", @"Failed to detect notch", nil);
}
}
@end
Keep in mind that for iOS, even though these files were created manually, you need to make sure they're imported as modules in Xcode.
With the files above ready, we finally call the NotchDetector module as follows in our React Native app
import {View, StyleSheet, BackHandler, NativeModules} from 'react-native';
const {NotchDetector} = NativeModules;
const Main_Screen = ({route}) => {
...
const notch = await NotchDetector.hasNotch();
// notch contain the result if the device have notch(dynamic island) or not
That's it.
Disclaimer
There is currently no official API or guideline that manufacturers are required to follow to provide developers with information about their device's dynamic island or notch section. So, while this solution covers returning whether or not a device has this physical feature, if you need information such as the height of this section on the screen, that isn't possible at this time.
Regards.
🪙 You can buy my projects and support me on:



Top comments (0)