레이아웃 위젯: Row, Column, Stack 사용해보기
반응형
이 강의에서는 Flutter의 주요 레이아웃 위젯인 Row, Column, Stack을 사용하여 화면 레이아웃을 구성하는 방법을 배워보겠습니다. 각 위젯의 사용법과 특징을 이해하고, 이를 활용하여 복잡한 레이아웃을 구현해보겠습니다.
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의 주요 속성
- 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의 주요 속성
- 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의 주요 속성
- 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,
),
],
),
],
),
),
),
);
}
}
실습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]),
),
],
),
),
],
),
);
}
}
코드 설명
- CircleAvatar: 사용자 프로필 이미지를 원형으로 표시합니다.
- SingleChildScrollView: 스크롤 가능한 화면을 만들어줍니다.
- Padding: 각 섹션에 여백을 추가하여 UI 요소들이 서로 겹치지 않도록 합니다.
- Text: 프로필 정보와 설명을 표시합니다.
- Divider: 각 섹션을 구분하는 선을 추가합니다.
- Wrap: 여러 Chip 위젯들을 감싸서 스킬 목록을 만들고, 자동으로 줄 바꿈을 처리합니다.
- ExperienceTile: 커스텀 위젯으로, 사용자 경험을 표시하는 데 사용됩니다. 이 위젯은 회사명, 역할, 기간을 포함한 정보를 표시합니다.
결론
이 강의를 통해 Flutter의 주요 레이아웃 위젯인 Row, Column, Stack을 사용하여 화면 레이아웃을 구성하는 방법을 학습했습니다. 각 위젯의 특징과 사용법을 이해하고, 이를 활용하여 복잡한 레이아웃을 구성해보았습니다. 다음 강의에서는 더 다양한 위젯(인터랙티브 위젯)을 활용하여 Flutter 애플리케이션을 더 멋지게 만드는 방법을 알아보겠습니다. Flutter로 창의적인 UI를 만들어봅시다!
반응형
댓글