
dual_screen_hinge
iPhone Duo-first foldable support for Flutter: continuous hinge angles, posture, reserved regions, screen role, and Android display modes.
Use it alongside MediaQuery
On Android, prefer MediaQuery.displayFeatures for adaptive layout and the
basic opened/half-opened state Flutter already exposes. Use this plugin when
you need continuous angles for animation, richer fold/hinge metadata,
supported postures, rear/dual-screen display sessions, or iOS support.
Install
dependencies:
dual_screen_hinge: ^0.2.1
Requires Flutter 3.38+, Dart 3.10+, Android API 21+, or iOS 13+. iPhone Duo
hinge telemetry requires a UIKit SDK that declares UIHingeInteraction.
Reserved-region geometry requires an SDK that declares reservedRegions.
CocoaPods and Swift Package Manager detect these APIs automatically; Xcode 27.0
SDKs without them keep the safe, unsupported fallback. No Podfile workaround
is needed. Runtime support still depends on the iOS version and hardware.
Read state and animate
final subscription = DualScreenHinge.instance.events.listen((state) {
print('${state.posture} ${state.hingeAngle}°');
});
StreamBuilder<double>(
stream: DualScreenHinge.instance.hingeAngleEvents,
builder: (context, snapshot) {
final angle = snapshot.data ?? 180;
return Transform.rotate(
angle: (180 - angle) * math.pi / 180,
child: const MyFoldEffect(),
);
},
);
The native event stream is shared by all Dart listeners, sends a snapshot on listen, deduplicates state, and coalesces sensor updates to approximately one per display frame.
Read regions for custom layout
final state = await DualScreenHinge.instance.currentState();
final activeRegionBounds = state.reservedRegions
.where((region) => region.isActive)
.map((region) => region.bounds)
.toList(growable: false);
On iOS 27.1, reservedRegions contains the folding region (division) and
camera regions (occlusion) in Flutter logical coordinates. Inactive regions
are included so a grid can, for example, prefer an even number of columns
before the fold becomes active. Active division regions are also exposed in
displayFeatures for cross-platform layout code.
Use MediaQuery.sizeOf(context), MediaQuery.paddingOf(context), and flexible
constraints for the overall layout. Use reserved regions only to displace
important custom-positioned elements using activeRegionBounds; don't drive
layout from the hinge angle or fixed iPhone Duo dimensions. See Apple's
iPhone Duo HIG.
Display modes (Android)
final capabilities = await DualScreenHinge.instance.capabilities();
if (capabilities.rearDisplay) {
await DualScreenHinge.instance.startRearDisplay();
}
if (capabilities.dualScreenPresentation) {
await DualScreenHinge.instance.startDualScreen(
entrypoint: 'dualScreenSecondaryMain',
arguments: ['initial payload'],
);
}
@pragma('vm:entry-point')
void dualScreenSecondaryMain(List<String> arguments) {
runApp(SecondaryDisplayApp(arguments: arguments));
}
Only one display session can be pending or active. V1 deliberately supports
startup arguments, not a cross-engine message bus. On iOS, display-mode methods
return DualScreenException(code: 'unsupported') because there is no equivalent
app-controlled public session API.
Platform behavior
| Capability | Android | iOS |
|---|---|---|
| Continuous angle | API 30+ TYPE_HINGE_ANGLE when present |
iOS 27 UIHingeInteraction on supported hardware |
| Fold geometry/posture | AndroidX WindowManager 1.5.1 | iOS 27 hinge status; iOS 27.1 reserved regions |
| Camera/fold avoidance | Flutter MediaQuery.displayFeatures |
Division and occlusion reserved regions on iOS 27.1 |
| Inner/outer identity | Only while a Window Area session establishes it | Region and scene evidence; unknown when multitasking is ambiguous |
| Rear-display transfer | Experimental Window Area API | Unsupported |
| Dual-screen presentation | Experimental Window Area API + secondary Flutter engine | Unsupported |
No device allowlist, OEM reflection, or private API is used. Unsupported data is nullable or reported through runtime capabilities.
Flutter-rendered toolbars don't automatically become UIKit's iPhone Duo vertical bars. Keep controls inside each independent safe-area edge, preserve their relative order across sizes, and let decorative backgrounds extend edge-to-edge separately from interactive content.
Documentation
See the documentation site,
the complete wire contract, device matrix,
the deployment guide, and testing guide.
The example/ app includes a
live fold animation and compares plugin output with MediaQuery.displayFeatures.
License
MIT. See LICENSE.
Libraries
- dual_screen_hinge
- Foldable display telemetry and controls for Android and iOS.