Something like CSS flexbox is what I'm thinking of
# doodle
a
Something like CSS flexbox is what I'm thinking of
n
can you share a quick example (mock-up) of the kind of layout you’d create? flexbox can be used in a range of ways; so i can recommend an approach more easily if i see what you’re trying to do.
a
Here's a data url of what I'm trying to recreate:
data:text/html,<html><head></head><body style="width: 100vw;height: 100vh;padding: 0;margin: 0;display: flex;flex-direction: column;"><div style="width: 100%;background-color: red;height: 100%;"></div><div style="width: 100%;background-color: blue;min-height: 100px;"></div></body></html>
. I'm looking for a horizontal version of this as well.
The red div/view takes up the rest of the space the blue view isn't using.
n
k. will take a look at this (likely in the morning) and share some recommendations.
a
Thank you!
n
you can do something like this if you need a vertical flex layout that works with any number of children. tweak with things like spacing between children etc.. and a similar thing for horizontal can be created separately or by having this layout take an
Orientation
.
Copy code
class FlexColumn: Layout {
        override fun layout(container: PositionableContainer) {
            var y               = <http://container.insets.top|container.insets.top>
            val x               = container.insets.left
            val w               = container.width  - container.insets.run { left + right }
            var remainingHeight = container.height - container.insets.run { top + bottom }
            val visibleChildren = container.children.filter { it.visible }

            val numChildrenCanIncrease = visibleChildren.size
            var minDecreaseAvailable   = -1.0
            var numChildrenCanDecrease = 0

            val updateMinDecreaseInfo: (child: Positionable) -> Unit = { child ->
                if (child.height > child.minimumSize.height) {
                    val decreaseAvailable = child.height - child.minimumSize.height
                    minDecreaseAvailable = if (minDecreaseAvailable < 0.0) decreaseAvailable else min(minDecreaseAvailable, decreaseAvailable)
                    ++numChildrenCanDecrease
                }
            }

            visibleChildren.forEach { child ->
                val h = child.idealSize?.height ?: child.minimumSize.height
                child.bounds = Rectangle(x, y, w, h)
                y += h
                remainingHeight -= h

                updateMinDecreaseInfo(child)
            }

            while (remainingHeight != 0.0) {
                y = <http://container.insets.top|container.insets.top>

                when {
                    remainingHeight > 0.0 -> {
                        val proportionalIncrease = remainingHeight / numChildrenCanIncrease
                        visibleChildren.forEach { child ->
                            child.bounds = Rectangle(child.x, y, child.width, child.height + proportionalIncrease)
                            y += child.height
                        }
                        remainingHeight = 0.0
                    }

                    remainingHeight < 0.0 -> {
                        when {
                            numChildrenCanDecrease > 0 -> {
                                val proportionalDecrease  = min(minDecreaseAvailable, -remainingHeight / numChildrenCanDecrease)
                                remainingHeight          += proportionalDecrease * numChildrenCanDecrease
                                numChildrenCanDecrease    = 0
                                minDecreaseAvailable      = -1.0

                                visibleChildren.forEach { child ->
                                    when {
                                        child.height > child.minimumSize.height -> {
                                            child.bounds = Rectangle(child.x, y, child.width, child.height - proportionalDecrease)
                                            y += child.height

                                            updateMinDecreaseInfo(child)
                                        }

                                        else -> child.bounds = Rectangle(child.x, y, child.width, child.height)
                                    }
                                }
                            }
                            else -> break
                        }
                    }
                }
            }
        }
    }
this kind of layout is generic and useful enough that i'll see if it can just be included in the framework.
a
Thanks! I tried it out and it seems to work well. The only change I made was moving the line
y += child.height
to after the
when
when doing the proportional decrease (because otherwise children that didn't decrease wouldn't change
y
). I haven't seen this issue because it wouldn't apply in my use case, but it looks like the proportional decrease could still violate views'
minimumSize
(e.g., one view can decrease 30 and another can decrease 10, but both are decreased 20, violating the view that could only decrease 10).
n
i’ll include a more robust version that supports orientation, insets and constant spacing between items in 0.9.3.