notch
Detect the position and shape of the device's camera cutout — notch, hole-punch, or Dynamic Island — and use it as the origin of overlays and animations. Android and iOS.
Features
- Detect the cutout: type, bounding boxes, and safe insets, reactive to
rotation via
MediaQuery. - Trace its outline as a
Path— the exact platform-supplied path on Android 12+, or a derived shape (capsule for a Dynamic Island, oval for a hole-punch, rounded rect for a notch) everywhere else. - Render a customizable overlay around it with
NotchOverlay. - Animate widgets emerging from the cutout with
NotchEmerge.
No dependencies beyond the Flutter SDK.
Requirements
- Flutter 3.44 or later (Dart 3.12 or later).
- Android API 24 or later.
- iOS 13 or later.
Quick start
import 'package:notch/notch.dart';
final notch = Notch.of(context); // sync, MediaQuery-reactive
print(notch.type); // NotchType.dynamicIsland
print(notch.primaryBounds); // Rect of the cutout, logical px
print(notch.center); // natural origin for animations
// For maximum accuracy (exact Android path, iOS per-model geometry):
final exact = await Notch.resolve(context);
print(exact.isExactPath); // true on Android 12+ when the OEM provides it
// Trace the cutout:
NotchOverlay(
color: Colors.lightBlueAccent,
child: yourContent,
)
// Animate content out of it:
NotchEmerge(
child: Text('Hello from the cutout 👋'),
)
See example/ for a complete demo app.
Setup
The cutout region belongs to the system unless your app draws edge-to-edge.
Android — allow drawing into the cutout (in
android/app/src/main/res/values/styles.xml, on your activity theme):
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
and enable edge-to-edge rendering:
SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
(Apps targeting Android 15+ are edge-to-edge by default.)
iOS — nothing to configure.
How it works — and accuracy
| Platform | Source | Accuracy |
|---|---|---|
| Android | Bounds: DisplayCutout rects via MediaQuery.displayFeatures. Path: DisplayCutout.getCutoutPath() via Notch.resolve |
Exact path on Android 12+ when the OEM provides it (isExactPath: true); bounding-rect outline otherwise |
| iOS | Machine-identifier lookup table (iPhone X → iPhone 17 family) via Notch.resolve; safe-area heuristic for unknown/future models |
Community-measured per-model values — close, not guaranteed pixel-perfect |
iOS has no public API for cutout geometry, so — like every iOS library in this space — values are hardcoded per device model. Unknown models degrade gracefully to the safe-area heuristic.
Testing without a cutout device
- Android emulator: Settings → Developer options → Display cutout to simulate a notch or hole-punch.
- iOS simulator: any iPhone X-or-later simulator reports real safe-area insets, so detection works as on hardware.
Known limitations
- iOS landscape: the cutout moves to a screen edge this package doesn't
model, so
NotchType.noneis reported. Android supplies rotated bounds and keeps working (including side-edge notches). - iOS Display Zoom: the family is still classified correctly, but the hardcoded point geometry is measured at standard zoom, so the traced outline can be a few points off on zoomed devices.
- Multi-cutout devices (rare, Android): each cutout gets a derived outline; the exact platform path is skipped to avoid stray connecting lines.
- Emulated cutouts (Android developer options): bounds always work; the exact path depends on the emulator image.
- Any platform-channel failure degrades to the derived shape — the package never throws from detection.
Coordinate space
All geometry is in logical pixels, window coordinates. NotchOverlay
should span the full window (e.g. wrap your page body). NotchEmerge maps the
cutout position into its own local space automatically.
Libraries
- notch
- Detect the position and shape of the device's camera cutout (notch, hole-punch, Dynamic Island) and use it as the origin of overlays and animations.