Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetpack Compose find parents width/length

I want to explicitely retrieve the value of the fillMaxSize(). Suppose i have:

    Box(Modifier
            .fillMaxSize()
            .background(Color.Yellow)) 
    {
var size = ?
Box(Modifier
            .size(someSize)
            .background(Color.Blue))
    {Text("Test")}

I want to change the size of my second Box multiple times (will probably stem from some viewmodel) and then reset it to maxSize.

How can i do that, I don't know any 'getMaxSize()'-method?

like image 832
Martin Avatar asked Apr 17 '21 12:04

Martin


People also ask

How do I screen size in jetpack compose?

If you want to get the size in pixels: val screenDensity = configuration. densityDpi / 160f and multiply with dp, for example val screenHeight = configuration. screenHeightDp.

What is LazyColumn in jetpack compose?

A LazyColumn is a vertically scrolling list that only composes and lays out the currently visible items. It's similar to a Recyclerview in the classic Android View system.

What is Mutablestateof in jetpack compose?

If you want to change the state of TextField and also update the UI, you can use a MutableState . Compose observes any reads and writes to the MutableState object and triggers a recomposition to update the UI.

What are jetpack compose modifiers?

The modifier design makes this kind of behavior explicit and predictable, and gives you more control to achieve the exact behavior you want. It also explains why there is not a margin modifier but only a padding one. Jetpack Compose provides a list of built-in modifiers to help you decorate or augment a composable.

What do you like most about jetpack compose?

One interesting thing about Jetpack Compose is this: it only measures children in layouts once. Measuring children in layouts twice will throw a runtime exception according to the documentation. I guess this helps with quickly rendering things on the screen.

How can a parent composable get sizing information about its children?

A parent composable can obtain sizing information about its children by accessing the Max and Min values of the Compose IntrinsicSize enumeration. IntrinsicSize provides the parent with information about the maximum or minimum possible width or height of its widest or tallest child.

What does jetpack mean?

Jetpack Compose is Android’s modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs. Discover the latest app development tools, platform updates, training, and documentation for developers across every Android device.


2 Answers

If you really need the raw size value, you can use the following code:

var size by remember { mutableStateOf(IntSize.Zero) }

Box(Modifier
    .fillMaxSize()
    .background(Color.Yellow)
    .onSizeChanged {
        size = it
    }
) {
    Box(
        Modifier
            .then(
                with(LocalDensity.current) {
                    Modifier.size(
                        width = size.width.toDp(),
                        height = size.height.toDp(),
                    )
                }
            )
            .background(Color.Blue)
    ) { Text("Test") }
}

But note, that is't not optimal in terms of performance: this view gets rendered two times. First time second box gets size zero, then the onSizeChanged block gets called, and then view gets rendered for the second time.

Be especially careful if using remember in top level views, because changing state will trigger full view stack re-render. Usually you want split your screen into views with states, so changing one view state only will re-render this view.

Also you can use BoxWithConstraints where you can get maxWidth/maxHeight inside the BoxWithConstraintsScope: it's much less code and a little better on performance.

BoxWithConstraints(
    Modifier
        .fillMaxSize()
        .background(Color.Yellow)
) {
    Box(
        Modifier
            .size(
                width = maxWidth,
                height = maxHeight,
            )
            .background(Color.Blue)
    ) { Text("Test") }
}

But usually if you wanna indicate size dependencies, using modifiers without direct knowing the size should be enough. It's more "Compose" way of writing code and more optimized one.

So if you wanna you second box be same size as the first one, just use .fillMaxSize() on it too. If you wanna it to be some part of the parent, you can add fraction param. To make second box size be half size of the first one, you do:

Box(
    Modifier
        .fillMaxSize(fraction = 0.5f)
) { Text("Test") }

If you wanna different parts for width/height:

Box(
    Modifier
        .fillMaxWidth(fraction = 0.3f)
        .fillMaxHeight(fraction = 0.7f)
) { Text("Test") }
like image 142
Philip Dukhov Avatar answered Oct 19 '22 18:10

Philip Dukhov


In your first Box you can use the onGloballyPositioned modifier to get the size.
It is called with the final LayoutCoordinates of the Layout when the global position of the content may have changed.

Then use coordinates.size to get the size of the first Box.

var size by remember { mutableStateOf(Size.Zero)}

Box(
    Modifier
        .fillMaxSize()
        .background(Color.Yellow)
        .onGloballyPositioned { coordinates ->
            size = coordinates.size.toSize()
        }
        Box(){ /*....*/ }
)
like image 34
Gabriele Mariotti Avatar answered Oct 19 '22 17:10

Gabriele Mariotti