Vidyesh Churi
Vidyesh Churi

Reputation: 2589

Support different screen sizes using android jetpack compose and also support foldable device posture like tabletop

I want to support devices like phone, tablets, foldables and tv. Will the following code work for that purpose ?

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            val windowSize = rememberWindowSizeClass()
            when (windowSize.widthWindowSizeClass) {
                is WindowSizeClass.WindowType.COMPACT -> {
                    CompactActivityUi()
                    /*TODO(reason = "Ui for COMPACT window")*/
                }
                is WindowSizeClass.WindowType.MEDIUM -> {
                    /*TODO(reason = "Ui for Medium window")*/
                }
                else -> {
                    /*TODO(reason = "Ui for EXPANDED window")*/
                }
            }
        }
    }
}

@Composable
fun CompactActivityUi() {
    AppTheme {
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {

        }
    }
}

data class WindowSizeClass(
    val widthWindowSizeClass: WindowType,
    val heightWindowSizeClass: WindowType,
    val widthWindowDpSize: Dp,
    val heightWindowDpSize: Dp
) {
    sealed class WindowType {
        object COMPACT : WindowType()
        object MEDIUM : WindowType()
        object EXPANDED : WindowType()
    }
}

@Composable
fun Activity.rememberWindowSizeClass(): WindowSizeClass {
    val configuration = LocalConfiguration.current
    val windowMetrics = remember(configuration) {
        WindowMetricsCalculator.getOrCreate()
            .computeCurrentWindowMetrics(activity = this)
    }
    val windowDpSize = with(LocalDensity.current) {
        windowMetrics.bounds.toComposeRect().size.toDpSize()
    }
    return WindowSizeClass(
        widthWindowSizeClass = when {
            windowDpSize.width < 0.dp -> throw IllegalArgumentException("Dp value cannot be negative")
            windowDpSize.width < 600.dp -> WindowSizeClass.WindowType.COMPACT
            windowDpSize.width < 840.dp -> WindowSizeClass.WindowType.MEDIUM
            else -> WindowSizeClass.WindowType.EXPANDED
        },
        heightWindowSizeClass = when {
            windowDpSize.height < 0.dp -> throw IllegalArgumentException("Dp value cannot be negative")
            windowDpSize.height < 480.dp -> WindowSizeClass.WindowType.COMPACT
            windowDpSize.height < 900.dp -> WindowSizeClass.WindowType.MEDIUM
            else -> WindowSizeClass.WindowType.EXPANDED
        },
        widthWindowDpSize = windowDpSize.width,
        heightWindowDpSize = windowDpSize.height
    )
}

@Preview(showBackground = true)
@Composable
fun DefaultPreview() {
    CompactActivityUi()
}

Official documentation

Official Sample

Official video

Will this code work for foldables, specially foldables in tabletop posture?

Is it recommended to have BottomNavigation on phone, Nav Rail on tablet and Navigation Drawer or T.V.

Upvotes: 1

Views: 2751

Answers (1)

khalp
khalp

Reputation: 71

The code you included will help you support devices of different sizes, but it won't detect foldable postures. To do that, you need to use the Jetpack Window Manager library to access FoldingFeature information (API reference).

The Jetcaster official Compose sample has an example of how to detect tabletop/book mode (MainActivity, WindowInfoUtil), but it's also important to note that some foldable devices have completely separate screens (even when flat). To support all kinds of foldables, I would recommend checking the FoldingFeature.isSeparating property in addition to FoldingFeature.state.

For more information about foldable support, you can check out these docs:

For navigation, I'm not familiar with the guidance for TV, but for other devices I think the recommendations depend on the current window size class. BottomNavigation is best for COMPACT width (most phones), while NavigationRail is better for MEDIUM and EXPANDED widths (tablets and larger foldables).

Upvotes: 3

Related Questions