I'd like to get the maximum dimension of a device ...
# compose
r
I'd like to get the maximum dimension of a device at app startup, but since that depends on the device's orientation,
BoxWithConstraints
does not look like the right tool for that. For example, on a Pixel 4A,
BoxWithConstraints
(at the top level, not within a
Scaffold
) will give
maxWidth
392.dp and
maxHeight
785.dp in portrait, and
maxWidth
801.dp and
maxHeight
348.dp in landscape. I'd like to know that 801.dp is the max, even if the app starts in portrait. Is there a way to do that? | Edit: Rationale in thread.
I have UI elements where the number of visible ones will vary depending on orientation, and I want to keep the state of hidden ones in case they rotate back into view (see https://kotlinlang.slack.com/archives/CJLTWPH7S/p1634665143417300 for more background). I'd like to initialize state for only the maximum number of elements possible on a given sized device, not the maximum number possible on the biggest possible sized device. (If configuration change were a callback and not a composition time determination I would just allocate the state for the extra elements when the width increased the first time, rather than at startup. I don't know how to do that with a
SideEffect
without introducing a noticeable delay before the new UI displays on the new configuration.) (The difference between 785.dp and 801.dp might not change the maximum number of elements in this example, but it seems in general better to have the exact number.)
j
I don’t know of a direct way to do this, but would max(maxWidth, maxHeight) work for what you need?
t
You want AndroidX WindowManager:
Copy code
fun Context.findActivity(): Activity? {
    var context = this
    while (context is ContextWrapper) {
        if (context is Activity) return context
        context = context.baseContext
    }
    return null
}

@Composable
fun ComposableFun() {
    val context = LocalContext.current
    val maxDimen = remember {
        WindowMetricsCalculator.getOrCreate()
            .computeMaximumWindowMetrics(context.findActivity!!)
            .bounds
            .toComposeRect()
            .maxDimension
    }
}
Keep in mind that these are the maximum window bounds, which ignores status and navigation insets, and aren't necessarily the bounds assigned to your window. You can use
WindowInfoRepository
to get a flow of current
WindowMetrics
values to use (say via
collectAsState
), which can be useful for supporting split-screen without relying on
BoxWithConstraints
or
SubcomposeLayout
.
z
As the other messages in this thread are getting at, first figure out what you actually want the dimensions of – the screen or the composable constraints? If it’s the latter, then yea just use the max function. It’s generally better to use the composable constraints if possible because then you can reuse your composable anywhere and it will adapt based on the available size.
☝🏻 1
r
I want the dimensions of the composable. Unless I'm missing your point I don't see how max(maxWidth, maxHeight) helps because I would need both orientations to get the max max,
max(max(maxWidth, maxHeight), max(maxWidth, maxHeight))
which in my example is max(max(392.dp, 785.dp), max( 801.dp, 348.dp)) = 801.dp
z
Oh I see what you mean, your parent composable is changing ratio as well. If you don't know what your parent composable is gonna do there then it’s impossible to predict. You could use screen dimensions but if the parent is effectively applying it's own padding to you then unless it tells you what it's gonna do there's nothing you can really do. If you control the parent too then you could maybe have it pass that information down (kinda like how Scaffold passes an inner padding too its content)