본문 바로가기

레이아웃 위젯: Row, Column, Stack 사용해보기

에온르 2024. 5. 26.
반응형

이 강의에서는 Flutter의 주요 레이아웃 위젯인 Row, Column, Stack을 사용하여 화면 레이아웃을 구성하는 방법을 배워보겠습니다. 각 위젯의 사용법과 특징을 이해하고, 이를 활용하여 복잡한 레이아웃을 구현해보겠습니다.

source : medium@apmntechdev

Row 위젯

Row 위젯은 자식 위젯들을 수평으로 배치하는 데 사용됩니다. 각 자식 위젯은 Row의 가로축을 따라 배열됩니다.

Row 사용법

import 'package:flutter/material.dart';

void main() {
  runApp(RowExampleApp());
}

class RowExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Row 위젯 예제'),
        ),
        body: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Icon(Icons.star, size: 50, color: Colors.red),
              Icon(Icons.star, size: 50, color: Colors.green),
              Icon(Icons.star, size: 50, color: Colors.blue),
            ],
          ),
        ),
      ),
    );
  }
}

row 위젯 예제 결과물

Row의 주요 속성

  • mainAxisAlignment: 주축(가로축) 방향으로 자식 위젯들의 정렬 방식을 설정합니다.
  • crossAxisAlignment: 교차축(세로축) 방향으로 자식 위젯들의 정렬 방식을 설정합니다.

Column 위젯

Column 위젯은 자식 위젯들을 수직으로 배치하는 데 사용됩니다. 각 자식 위젯은 Column의 세로축을 따라 배열됩니다.

Column 사용법

import 'package:flutter/material.dart';

void main() {
  runApp(ColumnExampleApp());
}

class ColumnExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Column 위젯 예제'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Icon(Icons.star, size: 50, color: Colors.red),
              Icon(Icons.star, size: 50, color: Colors.green),
              Icon(Icons.star, size: 50, color: Colors.blue),
            ],
          ),
        ),
      ),
    );
  }
}

column 위젯 예제 결과물

Column의 주요 속성

  • mainAxisAlignment: 주축(세로축) 방향으로 자식 위젯들의 정렬 방식을 설정합니다.
  • crossAxisAlignment: 교차축(가로축) 방향으로 자식 위젯들의 정렬 방식을 설정합니다.

Stack 위젯

Stack 위젯은 자식 위젯들을 겹쳐서 배치하는 데 사용됩니다. 각 자식 위젯은 Stack의 동일한 위치에 쌓이게 됩니다.

Stack 사용법

import 'package:flutter/material.dart';

void main() {
  runApp(StackExampleApp());
}

class StackExampleApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Stack 위젯 예제'),
        ),
        body: Center(
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Container(
                width: 200,
                height: 200,
                color: Colors.red,
              ),
              Container(
                width: 150,
                height: 150,
                color: Colors.green,
              ),
              Container(
                width: 100,
                height: 100,
                color: Colors.blue,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

stack 위젯 예제 결과물

Stack의 주요 속성

  • alignment: Stack 내에서 자식 위젯들의 정렬 방식을 설정합니다.
  • fit: 자식 위젯들의 크기 조정 방식을 설정합니다.

실습1: 복합 레이아웃 만들기

이제 Row, Column, Stack 위젯을 모두 사용하여 복합적인 레이아웃을 만들어보겠습니다.

import 'package:flutter/material.dart';

void main() {
  runApp(ComplexLayoutApp());
}

class ComplexLayoutApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('복합 레이아웃 예제'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: <Widget>[
                  Icon(Icons.star, size: 50, color: Colors.red),
                  Icon(Icons.star, size: 50, color: Colors.green),
                  Icon(Icons.star, size: 50, color: Colors.blue),
                ],
              ),
              SizedBox(height: 20),
              Stack(
                alignment: Alignment.center,
                children: <Widget>[
                  Container(
                    width: 200,
                    height: 200,
                    color: Colors.red,
                  ),
                  Container(
                    width: 150,
                    height: 150,
                    color: Colors.green,
                  ),
                  Container(
                    width: 100,
                    height: 100,
                    color: Colors.blue,
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

실습1) 복합 레이아웃 예제 결과물


실습2: 심화 레이아웃 구성하기

이번에는 더 심화된 레이아웃을 구성해보겠습니다. 이번 실습에서는 여러 개의 Row와 Column을 중첩하여 복잡한 레이아웃을 만들고, 다양한 위젯을 사용하여 완성된 프로필 페이지를 만들어보겠습니다.

심화 레이아웃 만들기

import 'package:flutter/material.dart';

void main() {
  runApp(AdvancedLayoutApp());
}

class AdvancedLayoutApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('심화 레이아웃 예제'),
        ),
        body: ProfilePage(),
      ),
    );
  }
}

class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Center(
              child: Column(
                children: <Widget>[
                  CircleAvatar(
                    radius: 50,
                    backgroundImage: NetworkImage('https://via.placeholder.com/150'),
                  ),
                  SizedBox(height: 16.0),
                  Text(
                    'Jane Doe',
                    style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
                  ),
                  Text(
                    'UI/UX Designer',
                    style: TextStyle(color: Colors.grey[700]),
                  ),
                ],
              ),
            ),
            SizedBox(height: 20),
            Divider(),
            SizedBox(height: 20),
            Text(
              'About Me',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            Text(
              'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus nec iaculis mauris. '
              'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; '
              'Curabitur quis libero leo, pharetra mattis eros. Praesent sed bibendum ligula. Suspendisse '
              'in ultricies velit, nec scelerisque ipsum. Quisque nec tortor a odio lobortis ultricies nec '
              'a magna. Nulla posuere a erat ut efficitur.',
              style: TextStyle(fontSize: 16),
            ),
            SizedBox(height: 20),
            Divider(),
            SizedBox(height: 20),
            Text(
              'Skills',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            Wrap(
              spacing: 10.0,
              runSpacing: 10.0,
              children: <Widget>[
                Chip(
                  label: Text('Adobe XD'),
                ),
                Chip(
                  label: Text('Figma'),
                ),
                Chip(
                  label: Text('Sketch'),
                ),
                Chip(
                  label: Text('Photoshop'),
                ),
                Chip(
                  label: Text('Illustrator'),
                ),
                Chip(
                  label: Text('InDesign'),
                ),
              ],
            ),
            SizedBox(height: 20),
            Divider(),
            SizedBox(height: 20),
            Text(
              'Experience',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            ExperienceTile(
              company: 'ABC Design Studio',
              role: 'Senior Designer',
              duration: '2019 - Present',
            ),
            ExperienceTile(
              company: 'XYZ Creative Agency',
              role: 'Junior Designer',
              duration: '2017 - 2019',
            ),
            ExperienceTile(
              company: 'LMN Tech Solutions',
              role: 'Intern',
              duration: '2016 - 2017',
            ),
          ],
        ),
      ),
    );
  }
}

class ExperienceTile extends StatelessWidget {
  final String company;
  final String role;
  final String duration;

  ExperienceTile({
    required this.company,
    required this.role,
    required this.duration,
  });

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget>[
          Icon(Icons.work, size: 30, color: Colors.blue),
          SizedBox(width: 10),
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  role,
                  style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                ),
                Text(
                  company,
                  style: TextStyle(fontSize: 16, color: Colors.grey[700]),
                ),
                Text(
                  duration,
                  style: TextStyle(fontSize: 14, color: Colors.grey[600]),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

실습2) 심화 레이아웃 예제 결과물

코드 설명

  1. CircleAvatar: 사용자 프로필 이미지를 원형으로 표시합니다.
  2. SingleChildScrollView: 스크롤 가능한 화면을 만들어줍니다.
  3. Padding: 각 섹션에 여백을 추가하여 UI 요소들이 서로 겹치지 않도록 합니다.
  4. Text: 프로필 정보와 설명을 표시합니다.
  5. Divider: 각 섹션을 구분하는 선을 추가합니다.
  6. Wrap: 여러 Chip 위젯들을 감싸서 스킬 목록을 만들고, 자동으로 줄 바꿈을 처리합니다.
  7. ExperienceTile: 커스텀 위젯으로, 사용자 경험을 표시하는 데 사용됩니다. 이 위젯은 회사명, 역할, 기간을 포함한 정보를 표시합니다.

결론

이 강의를 통해 Flutter의 주요 레이아웃 위젯인 Row, Column, Stack을 사용하여 화면 레이아웃을 구성하는 방법을 학습했습니다. 각 위젯의 특징과 사용법을 이해하고, 이를 활용하여 복잡한 레이아웃을 구성해보았습니다. 다음 강의에서는 더 다양한 위젯(인터랙티브 위젯)을 활용하여 Flutter 애플리케이션을 더 멋지게 만드는 방법을 알아보겠습니다. Flutter로 창의적인 UI를 만들어봅시다!

반응형

댓글