If I have a `Column` and I want it's content to be...
# compose
b
If I have a
Column
and I want it's content to be centered (vertically) on the screen, I can do:
Copy code
Column(modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center) { ... }
But what if I don't want it centered vertically, but instead want (the top of) it to be offest 35% from the top of the screen? I can use the
offset
modifier (
offset(y=100.dp)
) to place it a certain amount from the top, but I want to specify the offset by percentage, not dp ...
a
You can add a
Spacer(modifier = Modifier.fillMaxHeight(fraction = 0.35f))
.
b
ah, arrange the items to the "top", and then use the Spacer to push it down .. that would work
b
mind blown
@Adam Powell using
placeCenter
as a reference:
Copy code
internal fun placeCenter(totalSize: Int, size: IntArray, outPosition: IntArray) {
        val consumedSize = size.fold(0) { a, b -> a + b }
        var current = (totalSize - consumedSize).toFloat() / 2
        size.forEachIndexed { index, it ->
            outPosition[index] = current.roundToInt()
            current += it.toFloat()
        }
    }
I presume
totalSize
is the size of the container (column) itself,
size
is an array of the sizes of each item in the container, and
outPosition
is an array of positions at which to place each item in the container?
a
Yep, says as much right in the method docs ๐Ÿ™‚
b
Copy code
fun Arrangement.fromStart(@FloatRange(from = 0.0, to = 1.0) percent: Float): Arrangement.Horizontal {
    return object: Arrangement.HorizontalOrVertical {
        override val spacing = 0.dp

        override fun Density.arrange(totalSize: Int, sizes: IntArray, outPositions: IntArray) {
            place(percent, totalSize, sizes, outPositions)
        }

        override fun Density.arrange(
            totalSize: Int,
            sizes: IntArray,
            layoutDirection: LayoutDirection,
            outPositions: IntArray
        ) {
            when (layoutDirection) {
                LayoutDirection.Ltr -> place(percent, totalSize, sizes, outPositions)
                else -> {
                    sizes.reverse()
                    place(percent, totalSize, sizes, outPositions)
                    outPositions.reverse()
                }
            }
        }


    }
}

fun Arrangement.fromTop(@FloatRange(from = 0.0, to = 1.0) percent: Float): Arrangement.Vertical {
    return object: Arrangement.HorizontalOrVertical {
        override val spacing = 0.dp

        override fun Density.arrange(totalSize: Int, sizes: IntArray, outPositions: IntArray) {
            place(percent, totalSize, sizes, outPositions)
        }

        override fun Density.arrange(
            totalSize: Int,
            sizes: IntArray,
            layoutDirection: LayoutDirection,
            outPositions: IntArray
        ) {
            when (layoutDirection) {
                LayoutDirection.Ltr -> place(percent, totalSize, sizes, outPositions)
                else -> {
                    sizes.reverse()
                    place(percent, totalSize, sizes, outPositions)
                    outPositions.reverse()
                }
            }
        }
    }
}

private fun place(percent: Float, totalSize: Int, size: IntArray, outPosition: IntArray) {
    var current = (totalSize * percent)
    size.forEachIndexed { index, it ->
        outPosition[index] = current.roundToInt()
        current += it.toFloat()
    }
}
@Adam Powell, FTW!
And then ...
Copy code
Column(
    modifier = Modifier.fillMaxSize(), 
    verticalArrangement = Arrangement.percentFromStart(0.35F)) {
 ... 
}
๐Ÿ‘ 2
a
Working precisely as intended ๐Ÿ™‚
b
yall really should make things more difficult ๐Ÿ˜‰
๐Ÿ˜… 2
I edited the post above and broke it up into 2 more semantically named functions,
fromTop
which returns a
Vertical
and
fromStart
which returns a
Horizontal
in case anyone finds this and wants to use it. That seems to fall in line better with the other functions on
Arrangement
, like
spacedBy
๐Ÿ‘ 2