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.none is 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.