This is quite basic but in the case of a custom la...
# compose
n
This is quite basic but in the case of a custom layout, if I wanted to pass a measured value to another composable, is the best solution to use a View Model or is there a more straightforward way? Please see my code. I need to pass the
boardWidth
value elsewhere.
Copy code
@Composable
fun CustomLayout(modifier: Modifier, children: @Composable () -> Unit) {
    Layout(children, modifier) { measurables, constraints ->
        layout(constraints.maxWidth, constraints.maxHeight) {
            val boardWidth = constraints.maxWidth
            val tileSize = constraints.maxWidth / 7
            val childConstraints = constraints.copy(
                minWidth = minOf(constraints.minWidth, tileSize),
                maxWidth = tileSize
            )
            require(measurables.size == 2)
            measurables[0].measure(childConstraints).place(0, 0)
            measurables[1].measure(childConstraints).place(boardWidth - tileSize, 0)
        }
    }
}
k
What does that other composable do with it? There's a pattern, I think, in your questions here on "sharing" layout info across sub-trees in your view hierarchy, and that is not something that Compose encourages to do - as it makes it more difficult to reason about individual pieces as their own "units", so to speak. I can't speak to the larger intent behind your architecture, but perhaps it needs a higher level paradigm shift to not fight as actively against the way Compose works.
n
So my Tile composable has a draggable modifier, and I need to know how far I have dragged my tile on the board. Which is why I needed to measure the boardWidth.
k
In this new world, you'd either pass drag area bounds into each tile composeable, or have the board itself implement dragging.
n
hmm, but the board does not know it's own width... I need to look into "drag area bounds"... ๐Ÿ˜Š
a
+1 to having the board implement dragging. The board owns the layout positioning of each tile, so having the board also own the drag logic that alters that positioning keeps that responsibility in one place.
The board always knows the width and height of its children since it had to measure them, and it always knows its own width and height since those are the parameters it must pass to the
layout
function at the end of the layout dsl block ๐Ÿ™‚
k
And it can also enforce its own drag area limitations like paddings or even allow a tile to go slightly beyond its area for a bounce effect
n
So the board is more knowledgeable than me lol.
๐Ÿ˜„ 1
k
I will say that it takes some to adjust to the mental model of more encapsulated components.
n
Cheers, it's good to have advice for going in the right direction!
k
You want your composable tree to be Amazon, not Google
๐Ÿ˜‚ 4
n
Hi again, so I have spent quite a few hours going through the doc to try and work out how I can retrieve the position of the children from the board, but with no success. Could you please point me to the relevant doc? For now, here is what my board looks like:
Copy code
@Composable
fun GameBoard() {
    BoxWithConstraints(
        modifier = Modifier
            .fillMaxWidth()
            .aspectRatio(0.75f)
            .padding(20.dp)
            .background(Color.DarkGray)
            .clipToBounds()
    ) {
        val boxWidth = constraints.maxWidth
        println(boxWidth)

        CustomLayout(
            Modifier
                .fillMaxSize()
        ) {
            Column {
                repeat(7) {
                    Tile(Color.Magenta)
                }
            }
            Column {
                repeat(7) {
                    Tile(Color.Yellow)
                }
            }
        }
    }
}
Many thanks for your help! ๐Ÿ˜Š
a
BoxWithConstraints isn't necessary here, you aren't making any structural changes based on the constraint info, it's just being used as a very expensive
Layout
similarly the inner `Column`s are going to get in the way;
CustomLayout
will only see two direct children - those columns - and won't have any visibility to the `Tile`s, which seems to be the end goal
Column
is going to measure and place the tiles within it. The code above is delegating ownership of tile measurement/placement responsibility to
Column
, but you want to keep that ownership to yourself so that you can move and place things yourself. There's no need to retrieve positions from anything else if you're the one that placed them in the first place - in that arrangement you already have that data.
For the same reason you don't need
BoxWithConstraints
to tell you the available constraints; any invocation of
Layout
already gets that data too. You should never need to "leapfrog" layout information across layers this way
n
Thanks a lot, it makes sense! ๐Ÿ‘๐Ÿ™