# Base Solution

Let’s create our custom `ViewGroup` that can handle its children like in aforementioned gif. The main 2 methods that are important for new are `onMeasure` and `onLayout`.

## OnMeasure

The content of this method, will be similar to measuring `FrameLayout` with difference that we not need to find maximum height through all children, but sum all heights to resulting one:

`override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {    val fixedL = l + paddingLeft    val fixedT = t + paddingTop    val fixedR = r - paddingRight    val fixedB = b - paddingBottom    when(childCount) {        1 -> layoutOneChild(fixedL, fixedT, fixedR, fixedB)        2 -> layoutTwoChildren(fixedL, fixedT, fixedR, fixedB)        else -> layoutTreeChildren(fixedL, fixedT, fixedR, fixedB)    }}`

# 👍Boost 1️⃣: Extrapolate it for any child count

Now our task is to extrapolate our solution and invite new generic solution for any amount of children more than 1. To do that let’s think how we can approach the final algorithm.

## Concept of algorithm

The idea is to analyze distances between views when they already placed in case, when parent is really-really big, so children can be placed on their anchors correctly, without shifting. Each D_i consists of tree values:

• a half of height of View_(i+1) (for View_(n-1) it will be full height);
• remained height
`weight[i] = (view[i].height + view[i + 1].height) / 2weight[0] = view[0].height + view[1].height / 2weight[n - 2] = view[n - 2].height / 2 + view[n - 1].height`
`totalHeight = children.sum { it.height }`

## Implementation

Let’s start with implementing steps of our meta algoritm with appropriate methods and them we will little bit optimize them by memory. So let’s go step by step:

# Results

Here will be shown some results for random child count with random colors and heights:

## Concept

So we need to transform our task to the previous one. Suppose we now have `scales` and `weights` . If we will be able to scale down every `weight` by its `scale` we will be able to equalize every `weights` as they were if every `scale` would be equal to one (i.e in a aforementioned task). To do that we need to ensure that sum of all scales are equal to 1. In other words we need to normalize our `scales`.

1. Normalize `scales`
2. Adapt all `weights` (as we counted them earlier) with given `scales`
3. Distribute `freeHeights` between all `weights` properly applying `scales`
4. Build a distances
5. Build a layout

## Implementation

As the implementation will be an enhancement of previous implementation we will see pretty much same lines of code, but beside that we also introduce a new structure `Bucket` for convenient computing:

`private class Bucket(    val filled: Float,    val scales: Float,    val position: Int)`

# Results

Now let’s check what we can create with our new layout:

# Afterwords

In this article we solved one interesting task. And you know what? It doesn’t matter, if such layout is not needed in ordinary app development. More interesting that we came to that solution by ourself. It means that we leveled up our brain and skills and this is good :)

Love being creative to solve some problems with an simple and elegant ways

## More from Michael Spitsin

Love being creative to solve some problems with an simple and elegant ways