[Flutter] Column, Row 내에서의 위젯 가운데 정렬하기 with Center..Align..Flex..

Minji Jeong·2025년 1월 20일
0

Flutter/Dart

목록 보기
3/13
post-thumbnail

오늘은 단순하지만 한번 짚고 넘어가지 않으면 헷갈릴 수 있는, Center 또는 Flex widget (Column, Row)의 메인 속성들을 사용한 위젯 가운데 정렬 방법에 대해 잠깐 적어보고자 합니다.

플러터에서 위젯들을 화면의 중앙에 배치할 때 사용하는 방법은 Column 또는 Row 내에서 mainAxisAlignment, 주축과 crossAxisAlignment, 횡축을 center로 설정하거나 Column 또는 Row를 Center로 감싸주는 방법이 있습니다.

먼저, Column 내에서 자식 위젯들을 화면의 가운데에 정렬해보겠습니다. 참고로 Column의 각 축의 디폴트 값은 mainAxisAlignment-start, crossAxisAlignment-center로 정렬되어 있습니다. 이렇게만 생각해보면 마치 위젯은 아래 그림처럼 정렬될 것 같습니다.

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Column(
        children: <Widget>[
          Container(
            width: 100,
            height: 100,
            color: Colors.amber,
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.greenAccent,
          ),
        ],
      ),
    );
  }
}

하지만 생각한 것과는 결과가 다릅니다. Column의 mainAxisAlignment은 start이기 때문에 주축은 생각한 대로 정렬되지만, crossAxisAlignment이 center로 설정되어 있음에도 위젯은 화면의 가운데가 아닌 왼쪽 상단에 배치됩니다.

그럼 이번에는 Column의 mainAxisAlignment을 center로 설정해보겠습니다.

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Container(
            width: 100,
            height: 100,
            color: Colors.amber,
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.blue,
          ),
          Container(
            width: 100,
            height: 100,
            color: Colors.greenAccent,
          ),
        ],
      ),
    );
  }
}

Column의 mainAxisAlignment이 center이기 때문에 mainAxisAlignment 기준 가운데로 배치되었지만, crossAxisAlignment가 center임에도 crossAxisAlignment 기준 위젯은 여전히 start로 정렬되었습니다.

그렇다면 이번에는 Column을 Center로 감싸보겠습니다.

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Container(
              width: 100,
              height: 100,
              color: Colors.amber,
            ),
            Container(
              width: 100,
              height: 100,
              color: Colors.blue,
            ),
            Container(
              width: 100,
              height: 100,
              color: Colors.greenAccent,
            ),
          ],
        ),
      ),
    );
  }
}

우리가 원하는 대로, 위젯이 화면의 중앙에 정렬되었습니다. 왜 mainAxisAlignment와 crossAxisAlignment를 모두 center로 설정했음에도 위젯은 가운데로 배치되지 않고, 상위 위젯으로 Center를 배치해야 가운데 정렬이 되는것일까요?

Column과 Row에는 mainAxisSize라는 속성이 있습니다. 이름 그대로 유추할 수 있듯이 mainAxisSize는 주축이 차지할 수 있는 공간의 사이즈를 정할 수 있는 속성입니다.

mainAxisSize에는 max, min 두 속성이 정의되어 있으며 Column과 Row는 기본적으로 mainAxisSize가 max로 설정되어 있습니다.

속성정의
max최대 크기, 남은 공간을 모두 차지
min최소 크기, 포함된 자식 콘텐츠의 크기만큼 차지

따라서 최대로 커질 수 있는 주축의 사이즈를 미리 알고 있기 때문에 MainAxisAlignment.center를 사용한 위젯 정렬이 가능합니다. 하지만 횡축이 차지할 수 있는 공간의 사이즈를 지정할 수 있는 속성은 따로 정의되어 있지 않습니다.

그렇기 때문에 Row나 Column이나 SizedBox를 통해 width나 height를 정의하지 않으면, 횡축의 사이즈를 미리 알 수가 없어 crossAxisAlignment를 통한 횡축 정렬이 불가능합니다.

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: SizedBox(
          width: double.infinity,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: 100,
                height: 100,
                color: Colors.amber,
              ),
              Container(
                width: 100,
                height: 100,
                color: Colors.blue,
              ),
              Container(
                width: 100,
                height: 100,
                color: Colors.greenAccent,
              ),
            ],
          )),
    );
  }
}

그렇다면 Center를 통한 위젯 정렬이 가능한 이유는 무엇일까요?

Center는 Align을 상속하고 있습니다.

또한 Align의 default alignment 값은 center 입니다.

Center와 달리 Column과 Row는 Flex를 상속하고 있습니다.

Flex vs Align

  • 여기서 잠깐 Flex와 Align의 차이를 말하자면, Flex는 여러개의 자식 위젯들을 특정 방향으로 배치할 때 사용하는 위젯 클래스로, 레이아웃을 정렬하거나 공간을 나누는 데 적합합니다. 반면 Align은 하나의 자식 위젯을 부모 위젯 내에서 특정 위치에 배치하고 싶을 때 사용하기 적합한 클래스입니다.

따라서 Center 대신 Align.center를 적용해도 동일한 결과가 출력됩니다.

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(title),
      ),
      body: Align(
          alignment: Alignment.center,
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Container(
                width: 100,
                height: 100,
                color: Colors.amber,
              ),
              Container(
                width: 100,
                height: 100,
                color: Colors.blue,
              ),
              Container(
                width: 100,
                height: 100,
                color: Colors.greenAccent,
              ),
            ],
          )),
    );
  }
}

References

꼬물꼬물 개발일기 - MainAxis와 CrossAxis

profile
Software Engineer

0개의 댓글