Вычисление окончательных ширин дочерних элементов внутри контейнера

Сначала вычитаем фиксированные ширины, затем распределяем остаток пропорционально модулям отрицательных коэффициентов. Округление нужно согласовать так, чтобы не терять пиксели.

Короткий ответ

Что ответить на собеседовании

Сначала вычитаем фиксированные ширины, затем распределяем остаток пропорционально модулям отрицательных коэффициентов. Округление нужно согласовать так, чтобы не терять пиксели.

Подробный разбор

Ответ с пояснениями

Условие

Дано:

  • parentWidth — общая ширина родительского контейнера.

  • childSpecs — список спецификаций ширин дочерних View, представленных целыми числами, где:

    • Если childSpecs[i] ≥ 0, то соответствующая View имеет фиксированную ширину, равную этому значению.
    • Если childSpecs[i] < 0, то это коэффициент, определяющий долю от оставшегося после размещения всех фиксированных View свободного пространства parentWidth. Необходимо рассчитать итоговые ширины всех View. Пример: measureWidths(100, listOf(50, -3, -2)) должно вернуть listOf(50, 30, 20).
fun measureWidths(parentWidth: Int, childSpecs: List<Int>): List<Int> {
 // your code
}

Ответ

Сначала вычитаем фиксированные ширины, затем распределяем остаток пропорционально модулям отрицательных коэффициентов. Округление нужно согласовать так, чтобы не терять пиксели.

Вариант распределяет округление через накопленные доли и запрещает переполнение контейнера фиксированными View:

fun measureWidths(parentWidth: Int, childSpecs: List<Int>): List<Int> {
    require(parentWidth >= 0)
    val fixed = childSpecs.filter { it >= 0 }.sumOf { it.toLong() }
    require(fixed <= parentWidth.toLong())
    val remaining = parentWidth.toLong() - fixed
    val weight = childSpecs.filter { it < 0 }.sumOf { -it.toLong() }
    var cumulative = 0L
    var allocated = 0L
    return childSpecs.map { spec ->
        if (spec >= 0) spec else {
            cumulative += -spec.toLong()
            val next = remaining * cumulative / weight
            val width = next - allocated
            allocated = next
            width.toInt()
        }
    }
}

В данном виде произведение remaining * cumulative требует, чтобы оно помещалось в Long; для экстремально больших списков используйте BigInteger. Если весовых элементов нет, свободное место остаётся незанятым. Пример даёт [50, 30, 20].

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее