Avatar ·

Как выровнять содержимое Column по центру в Jetpack Compose?

Привет! Я только начал изучать Jetpack Compose и столкнулся с, казалось бы, простой задачей: нужно разместить несколько элементов внутри Column по центру экрана, но у меня ничего не получается.

Вот мой код:

@Composable
fun MyScreen() {
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        Text("Привет, мир!")
        Button(onClick = { }) {
            Text("Нажми меня")
        }
        Text("Нижний текст")
    }
}

Всё прижимается к верхнему левому углу. Я перепробовал разные модификаторы: Modifier.align(Alignment.CenterHorizontally) на каждом элементе — это работает только по горизонтали, но по вертикали они всё равно вверху. Пытался добавить Modifier.weight(1f) — стало хуже, элементы растянулись. Пробовал verticalArrangement с Arrangement.Center — тоже не дало нужного эффекта.

Подскажите, как сделать так, чтобы вся колонка отображалась ровно посередине экрана (и по горизонтали, и по вертикали), а не начиналась от верхнего края? Какой правильный способ центрирования содержимого в Column?

Заранее спасибо!

<<>>

Правильное центрирование Column в Jetpack Compose

Проблема в том, что вы пытаетесь выровнять содержимое внутри Column, но сама Column занимает всю доступную площадь и по умолчанию располагается в левом верхнем углу родительского контейнера. Чтобы центрировать всю колонку целиком, нужно использовать модификатор Modifier.align() на уровне родительского контейнера, а не внутри самой колонки.

Вот несколько правильных подходов:

Способ 1: Использование Box (рекомендуется)

Самый простой и наглядный способ — обернуть Column в Box с центрированием:

@Composable
fun MyScreen() {
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center  // ← центрируем содержимое Box
    ) {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally  // ← центрируем элементы по горизонтали внутри колонки
        ) {
            Text("Привет, мир!")
            Button(onClick = { }) {
                Text("Нажми меня")
            }
            Text("Нижний текст")
        }
    }
}

Здесь Box занимает весь экран, а параметр contentAlignment = Alignment.Center указывает, что его дочерний элемент (вся колонка) должен быть расположен ровно посередине. Внутри колонки мы дополнительно центрируем элементы по горизонтали с помощью horizontalAlignment.

Способ 2: Column с модификатором align

Можно обойтись без Box, если использовать Column внутри другого Column или Row с модификатором align:

@Composable
fun MyScreen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,  // ← центрирование по вертикали
        horizontalAlignment = Alignment.CenterHorizontally  // ← центрирование по горизонтали
    ) {
        Text("Привет, мир!")
        Button(onClick = { }) {
            Text("Нажми меня")
        }
        Text("Нижний текст")
    }
}

Обратите внимание: verticalArrangement работает только если Column имеет фиксированную высоту (или fillMaxSize()) и её содержимое меньше этой высоты. Arrangement.Center равномерно распределяет свободное пространство вокруг содержимого, что даёт эффект центрирования по вертикали.

Способ 3: Использование Modifier.weight()

Если вам нужно, чтобы один из элементов занимал всё доступное пространство и "толкал" остальные к центру, используйте weight:

@Composable
fun MyScreen() {
    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Spacer(modifier = Modifier.weight(1f))  // пустое пространство сверху
        Text("Привет, мир!")
        Button(onClick = { }) {
            Text("Нажми меня")
        }
        Text("Нижний текст")
        Spacer(modifier = Modifier.weight(1f))  // пустое пространство снизу
    }
}

Этот способ даёт более гибкий контроль, особенно если нужно центрировать группу элементов, но при этом оставить место для других компонентов сверху или снизу.

Важные моменты:

  • Не путайте verticalArrangement (распределение дочерних элементов внутри колонки) и contentAlignment (выравнивание самой колонки внутри родителя).
  • Modifier.align() внутри Column работает только для выравнивания отдельных дочерних элементов относительно колонки, а не для центрирования всей колонки.
  • Для сложных макетов используйте комбинацию Box + Column — это самый читаемый и предсказуемый подход.

Выберите первый способ (с Box) как самый простой и наглядный для вашей задачи.

<<>>

Альтернатива: использование ConstraintLayout

Если вы знакомы с ConstraintLayout из классического Android View, в Compose тоже есть аналогичный компонент. Он может быть полезен, когда нужно центрировать элемент относительно других или с привязкой к границам:

@Composable
fun MyScreen() {
    ConstraintLayout(
        modifier = Modifier.fillMaxSize()
    ) {
        val (columnRef) = createRefs()
        
        Column(
            modifier = Modifier.constrainAs(columnRef) {
                centerTo(parent)  // ← центрирование относительно родителя
            },
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text("Привет, мир!")
            Button(onClick = { }) {
                Text("Нажми меня")
            }
            Text("Нижний текст")
        }
    }
}

Метод centerTo(parent) автоматически центрирует элемент как по горизонтали, так и по вертикали. Это может быть удобно, если в будущем вы захотите добавить дополнительные элементы с привязками (например, кнопку в правом нижнем углу).

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