notch 1.0.0
notch: ^1.0.0 copied to clipboard
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. Android and iOS.
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.