Developing for Tablets, Foldables, and Large Screens in Android

The Android large screen ecosystem has grown substantially. Foldables, tablets, and Chromebooks running Android apps collectively represent hundreds of millions of active devices. Google has made large screen quality a Play Store ranking signal — making this a business priority, not just a nice-to-have.

The Window Size Class System

Never branch on screen size using device type or pixel density. Use Window Size Classes from Jetpack material3-window-size-class.

  • Compact — phone in portrait (<600dp wide). Single-pane layout.
  • Medium — tablet in portrait, unfolded foldable in portrait (600–840dp). Two-pane optional.
  • Expanded — tablet in landscape, unfolded foldable in landscape (>840dp). Two-pane required.
@Composable
fun AdaptiveApp() {
    val windowSizeClass = calculateWindowSizeClass(LocalContext.current as Activity)

    when (windowSizeClass.widthSizeClass) {
        WindowWidthSizeClass.Compact -> SinglePaneLayout()
        WindowWidthSizeClass.Medium -> MediumLayout()
        WindowWidthSizeClass.Expanded -> TwoPaneLayout()
    }
}

Navigation Patterns by Screen Size

  • Compact — Bottom Navigation Bar (5 items max).
  • Medium — Navigation Rail (icons on the left side).
  • Expanded — Navigation Drawer (persistent, always visible).
@Composable
fun AppNavigation(windowSizeClass: WindowSizeClass) {
    when (windowSizeClass.widthSizeClass) {
        WindowWidthSizeClass.Compact ->
            BottomNavigation { /* tabs */ }
        WindowWidthSizeClass.Medium ->
            NavigationRail { /* items */ }
        else ->
            PermanentNavigationDrawer(drawerContent = { /* nav */ }) { /* content */ }
    }
}

List-Detail Layout

The most important pattern for large screens: show a list and detail side by side on wide screens, and navigate sequentially on compact screens.

// Jetpack Adaptive layout
ListDetailPaneScaffold(
    directive = calculatePaneScaffoldDirective(currentWindowAdaptiveInfo()),
    value = navigator.scaffoldValue,
    listPane = {
        AnimatedPane { ArticleList(onArticleClick = navigator::navigateTo) }
    },
    detailPane = {
        AnimatedPane {
            val article = navigator.currentDestination?.content
            if (article != null) ArticleDetail(article) else NoArticleSelected()
        }
    }
)

Foldables: Handling the Fold

Foldable devices have a hinge that creates a "fold" area. Content should not be placed over the fold. Use Jetpack WindowManager to detect fold state.

val windowInfoTracker = WindowInfoTracker.getOrCreate(context)
windowInfoTracker.windowLayoutInfo(activity).collect { info ->
    val fold = info.displayFeatures.filterIsInstance<FoldingFeature>().firstOrNull()
    fold?.let {
        val isTableTop = it.state == FoldingFeature.State.HALF_OPENED
            && it.orientation == FoldingFeature.Orientation.HORIZONTAL
        if (isTableTop) showTableTopLayout() else showNormalLayout()
    }
}

Testing Large Screen Layouts

  • Use the Resizable Emulator in Android Studio to test all form factors without physical devices.
  • Test rotation — apps must handle configuration changes gracefully.
  • Test multi-window and split-screen — your app must work correctly as a non-fullscreen window.
  • Test the fold open/close transition on foldable emulators.