Developer guide
Foldables: detecting the fold
How Android reports a fold
A Galaxy Z Fold or Flip reports its hinge as a FoldingFeature, one of the display features in WindowLayoutInfo from Jetpack WindowManager. It is not a window inset: the fold never changes systemBars or displayCutout, so pad for insets and lay out around the fold separately. Each feature has:
state:FLAT(fully open) orHALF_OPENED(partly folded).orientation:VERTICALfor a book fold such as Galaxy Z Fold,HORIZONTALfor a clamshell such as Galaxy Z Flip.isSeparating: whether the fold splits the window into two logical areas. It is alwaystruewhileHALF_OPENED.occlusionType:NONEorFULL, whether the fold hides part of the display.bounds: the fold's rectangle in window coordinates (px).
A closed device reports no folding feature. The app then runs on the cover display, which is a separate screen with its own insets. On this site, choose Cover or Main on a foldable's page to see each one.
The recordings below show what each posture reports as the hinge moves through 0°, the partly open range and 180°:
Recorded from this site's 3D renderer with the measured cover and inner displays. The angle where the animation turns from the cover to the inner display is illustrative; real devices switch displays at their own angle.
Jetpack Compose
Compose Material 3 Adaptive (androidx.compose.material3.adaptive:adaptive) provides collectFoldingFeaturesAsState(), which recomposes whenever the fold changes. The posture checks below follow Android's Make your app fold aware guide.
@Composable
fun FoldAwareScreen() {
val foldingFeatures by collectFoldingFeaturesAsState()
val fold = foldingFeatures.firstOrNull()
val isTabletop = fold?.state == FoldingFeature.State.HALF_OPENED &&
fold.orientation == FoldingFeature.Orientation.HORIZONTAL
val isBook = fold?.state == FoldingFeature.State.HALF_OPENED &&
fold.orientation == FoldingFeature.Orientation.VERTICAL
when {
isTabletop -> TabletopLayout(foldBounds = fold!!.bounds) // content above, controls below
isBook -> TwoPaneLayout(foldBounds = fold!!.bounds) // one pane on each side
else -> SinglePaneLayout()
}
}If you only need the posture, currentWindowAdaptiveInfoV2().windowPosture exposes it directly, for example windowPosture.isTabletop.
Views
With Views, collect WindowInfoTracker (androidx.window:window) while the activity is started:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
WindowInfoTracker.getOrCreate(this@MainActivity)
.windowLayoutInfo(this@MainActivity)
.collect { layoutInfo ->
val fold = layoutInfo.displayFeatures
.filterIsInstance<FoldingFeature>()
.firstOrNull()
updateLayoutForFold(fold) // null when flat without a fold or closed
}
}
}
}Hinge angle
FoldingFeature does not expose the angle. If you need it, read Sensor.TYPE_HINGE_ANGLE (API 30+) through SensorManager. Reporting ranges and accuracy vary by device, so prefer state and orientation for layout decisions. The hinge slider on this site's foldable pages is a visualization; the measured insets come from captures of the open and closed displays.
For design guidance on cover and inner screens, see Samsung's Designing for foldables, and for app-level patterns, Android's Learn about foldables.
Found an issue or want to contribute?
Open an issue or pull request on GitHub. If you have a device and want to add insets data, use InsetsProbe and share your JSON.