1. UI 구성 (User Interface)
1. 기본 레이아웃 구조
-
Flutter에서 UI를 구성할 때 가장 기본이 되는 개념은 위젯 트리입니다.
-
모든 화면 요소는 위젯으로 구성되며, 부모-자식 관계를 통해 화면이 구조화됩니다.
-
아래와 같이 화면의 구성요소를 나누고 각각의 요소들을 위젯으로 나누어 컴포넌트합니다.
컴포넌트화
- 화면을 구성하는 요소를 여러 블록으로 쪼개서 컴포넌트(화면을 구성하는 각 부분)로 만드는 작업

- Flutter에서 UI를 배치할 때 사용하는 주요 레이아웃 위젯을 정리하면 다음과 같습니다.
📌 1-1. Column (세로 정렬)
- 위젯들을 세로(위→아래)로 배치할 때 사용합니다.
- 자식 위젯들은
children 리스트에 추가합니다.
mainAxisAlignment와 crossAxisAlignment를 이용해 정렬을 조정할 수 있습니다.
✅ 예제 코드
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("첫 번째 아이템"),
Text("두 번째 아이템"),
Text("세 번째 아이템"),
],
)
✅ 주요 속성
| 속성 | 설명 |
|---|
mainAxisAlignment | 세로 방향 정렬 방식 (start, center, end, spaceAround, spaceBetween, spaceEvenly) |
crossAxisAlignment | 가로 방향 정렬 방식 (start, center, end, stretch) |
mainAxisSize | Column의 크기 조절 (max: 가능한 모든 공간 차지, min: 내용만큼 크기 조절) |
📌 1-2. Row (가로 정렬)
- 위젯들을 가로(왼쪽→오른쪽)로 배치할 때 사용합니다.
Column과 사용법이 거의 동일하지만, mainAxisAlignment와 crossAxisAlignment의 기준이 가로축과 세로축으로 바뀜에 주의해야 합니다.
✅ 예제 코드
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(Icons.star, size: 50),
Icon(Icons.favorite, size: 50),
Icon(Icons.thumb_up, size: 50),
],
)
📌 1-3 AppBar 위젯
- AppBar는
Scaffold의 상단에 배치되는 위젯으로, 보통 앱의 제목, 아이콘, 검색 기능 등을 포함하여 네비게이션을 지원합니다.
AppBar는 leading, title, actions, flexibleSpace, bottom 영역으로 나뉘어 다양한 UI 요소를 설정할 수 있습니다.
✅ 예제 코드
AppBar(
title: const Text('AppBar Demo'),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.add_alert),
tooltip: 'Show Snackbar',
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('This is a snackbar')));
},
),
IconButton(
icon: const Icon(Icons.navigate_next),
tooltip: 'Go to the next page',
onPressed: () {},
),
],
)
✅ 주요 속성
| 속성 | 설명 |
|---|
title | AppBar에 표시할 주 제목을 설정합니다. |
leading | AppBar의 왼쪽에 위치하는 위젯을 설정합니다 (예: 메뉴 아이콘). |
actions | AppBar의 오른쪽에 위치하는 위젯들을 리스트로 추가합니다 (예: 아이콘 버튼들). |
flexibleSpace | AppBar의 배경에 고정되지 않은 영역으로, 원하는 레이아웃을 추가할 수 있습니다. |
bottom | AppBar 아래에 위치하는 위젯을 설정합니다 (예: TabBar). |
📌 1-4. Stack (겹쳐진 레이아웃)
- 여러 위젯을 겹쳐서 배치할 때 사용합니다.
- 기본적으로 자식 위젯들이 왼쪽 상단(0,0) 좌표를 기준으로 배치됩니다.
Positioned 위젯을 사용하여 원하는 위치를 지정할 수 있습니다.
✅ 예제 코드
Stack(
children: [
Container(width: 200, height: 200, color: Colors.blue),
Positioned(
top: 50,
left: 50,
child: Container(width: 100, height: 100, color: Colors.red),
),
],
)
✅ 주요 속성
| 속성 | 설명 |
|---|
alignment | 정렬 방식 지정 (Alignment.center, Alignment.bottomRight 등) |
fit | 부모 위젯을 채우는 방식 (StackFit.loose: 기본 크기 유지, StackFit.expand: 최대 크기 차지) |
clipBehavior | 넘치는 부분을 자를지 여부 (Clip.none, Clip.hardEdge 등) |
📌 1-5. Expanded (유동적인 크기 조정)
- 부모 위젯의 남은 공간을 유동적으로 차지할 때 사용합니다.
Column이나 Row 내부에서만 사용할 수 있습니다.
✅ 예제 코드
Row(
children: [
Expanded(
flex: 2,
child: Container(color: Colors.red, height: 100),
),
Expanded(
flex: 1,
child: Container(color: Colors.blue, height: 100),
),
],
)
📌 1-6. SizedBox (고정 크기의 빈 공간 추가)
- 특정 크기의 빈 공간을 만들거나, 위젯의 크기를 제한하는 데 사용됩니다.
width와 height 값을 지정하면 해당 크기만큼의 공간을 차지합니다.
✅ 예제 코드
Column(
children: [
Text("첫 번째 텍스트"),
SizedBox(height: 20),
Text("두 번째 텍스트"),
],
)
📌 1-7. Spacer (균등한 간격 조절)
Row나 Column에서 위젯 간의 간격을 균등하게 분배할 때 사용됩니다.
flex 값을 조절하면 공간을 원하는 비율로 나눌 수 있습니다.
✅ 예제 코드
Row(
children: [
Icon(Icons.star, size: 50),
Spacer(flex: 1),
Icon(Icons.favorite, size: 50),
Spacer(flex: 2),
Icon(Icons.thumb_up, size: 50),
],
)
정리
| 위젯 | 역할 |
|---|
Column | 세로 정렬 |
Row | 가로 정렬 |
AppBar | 상단 바에 제목, 아이콘, 메뉴 등을 표시 |
Stack | 위젯 겹치기 |
Expanded | 남은 공간을 유동적으로 채우기 |
SizedBox | 특정 크기의 빈 공간 추가 |
Spacer | 위젯 간 간격 조절 |
2. 위젯 배치 및 스타일
Flutter에서는 UI의 디자인을 위해 여백, 정렬, 크기 조절, 색상 등의 스타일 속성을 활용할 수 있습니다.
- 주요한 스타일링 위젯들을 정리하면 다음과 같습니다.
📌 2-1. Padding (내부 여백 추가)
- 위젯 내부의 여백(패딩)을 추가할 때 사용됩니다.
- 부모 위젯과의 간격을 조절하는 역할을 합니다.
✅ 예제 코드
Padding(
padding: EdgeInsets.all(16.0),
child: Text("패딩이 적용된 텍스트"),
)
🔹 주요 속성
| 속성 | 설명 |
|---|
EdgeInsets.all(값) | 모든 방향에 동일한 여백 추가 |
EdgeInsets.symmetric(horizontal: 값, vertical: 값) | 가로/세로 여백 개별 설정 |
EdgeInsets.only(left: 값, right: 값, top: 값, bottom: 값) | 특정 방향에만 여백 추가 |
📌 2-2. Margin (외부 여백 추가)
- 위젯 바깥쪽의 여백(마진)을 추가할 때 사용됩니다.
- 마진은
Container의 margin 속성으로 설정할 수 있습니다.
✅ 예제 코드
Container(
margin: EdgeInsets.all(20.0),
color: Colors.blue,
child: Text("마진이 적용된 컨테이너"),
)
📌 2-3. Alignment & Center (정렬)
위젯을 특정 위치에 정렬할 때 사용됩니다.
Alignment.center: 중앙 정렬
Alignment.topLeft: 왼쪽 상단 정렬
Alignment.bottomRight: 오른쪽 하단 정렬
✅ 예제 코드
Container(
width: 200,
height: 200,
alignment: Alignment.bottomRight,
color: Colors.green,
child: Text("정렬된 텍스트"),
)
🔹 Center 위젯을 사용한 중앙 정렬
Center(
child: Text("이 텍스트는 중앙에 배치됨"),
)
📌 2-4. Container (스타일링이 가능한 박스)
Container는 배경색, 테두리, 크기 조정, 패딩 등을 적용할 수 있는 다목적 위젯입니다.
✅ 예제 코드
Container(
width: 150,
height: 150,
padding: EdgeInsets.all(16),
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.orange,
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.black, width: 2),
),
child: Text("컨테이너 스타일"),
)
🔹 주요 속성
| 속성 | 설명 |
|---|
width, height | 크기 지정 |
padding | 내부 여백 |
margin | 외부 여백 |
color | 배경색 지정 |
borderRadius | 모서리 둥글게 |
border | 테두리 설정 |
📌 2-5. AspectRatio (비율 유지)
- 위젯의 크기를 특정 비율로 고정할 때 사용됩니다.
- 예를 들어,
aspectRatio: 16/9는 16:9 비율을 유지하는 컨테이너를 만듭니다.
✅ 예제 코드
AspectRatio(
aspectRatio: 16 / 9,
child: Container(color: Colors.blue),
)
📌 정리
| 위젯 | 역할 |
|---|
Padding | 내부 여백 추가 |
Margin | 외부 여백 추가 |
Alignment | 특정 위치로 정렬 |
Center | 중앙 정렬 |
Container | 스타일 적용 가능한 박스 |
AspectRatio | 특정 비율 유지 |
3. 이미지 및 리소스 관리
- Flutter에서 이미지를 불러오는 방식에는 프로젝트 내부 이미지, 인터넷 이미지, 디바이스 저장소 이미지 등이 있습니다.
- 각 방식별로 사용하는 위젯과 예제를 정리했습니다.
📌 3-1. 프로젝트 내부 이미지 (Asset Image)
앱 내부에 포함된 이미지를 표시할 때 사용됩니다.
이 경우, pubspec.yaml 파일에 이미지 경로를 등록해야 합니다.
✅ 설정 방법
assets/ 폴더를 프로젝트 루트에 생성
pubspec.yaml 파일에 아래 내용 추가
flutter:
assets:
- assets/images/logo.png
Image.asset() 위젯을 사용하여 이미지 표시
✅ 예제 코드
Image.asset(
'assets/images/logo.png',
width: 100,
height: 100,
fit: BoxFit.cover,
)
📌 3-2. 인터넷 이미지 (Network Image)
- 웹에서 이미지를 불러올 때 사용됩니다.
- 인터넷 연결이 필요하며, 캐싱이 적용되지 않으므로 주의해야 합니다.
✅ 예제 코드
Image.network(
'https://example.com/sample.jpg',
width: 150,
height: 150,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Center(child: CircularProgressIndicator());
},
errorBuilder: (context, error, stackTrace) {
return Icon(Icons.error, color: Colors.red);
},
)
🔹 네트워크 이미지 캐싱을 적용하려면?
Flutter의 cached_network_image 패키지를 사용하면 이미지 캐싱이 가능합니다.
설치:
dependencies:
cached_network_image: ^3.3.0
사용:
CachedNetworkImage(
imageUrl: "https://example.com/sample.jpg",
placeholder: (context, url) => CircularProgressIndicator(),
errorWidget: (context, url, error) => Icon(Icons.error),
)
📌 3-3. 로컬 저장소 이미지 (File Image)
- 사용자가 디바이스에 저장한 이미지를 불러올 때 사용됩니다.
- 이를 위해
image_picker 패키지가 필요합니다.
✅ 설치 방법
dependencies:
image_picker: ^1.0.4
✅ 예제 코드 (갤러리에서 이미지 가져오기)
import 'package:image_picker/image_picker.dart';
import 'dart:io';
File? _image;
Future<void> pickImage() async {
final ImagePicker picker = ImagePicker();
final XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
setState(() {
_image = File(pickedFile.path);
});
}
}
@override
Widget build(BuildContext context) {
return Column(
children: [
ElevatedButton(
onPressed: pickImage,
child: Text("갤러리에서 이미지 선택"),
),
_image != null ? Image.file(_image!) : Text("이미지를 선택하세요."),
],
);
}
📌 3-4. 메모리에서 이미지 로드 (Memory Image)
` 네트워크에서 가져온 이미지를 바이트 배열로 변환하여 메모리에 저장하고 표시할 수 있습니다.
✅ 예제 코드
import 'dart:typed_data';
Uint8List imageData = Uint8List.fromList([]);
Image.memory(
imageData,
width: 200,
height: 200,
)
📌 3-5. 이미지 크기 조정 및 스타일 (BoxFit)
- 이미지를 다양한 방식으로 조정할 수 있습니다.
BoxFit을 사용하면 이미지 크기를 컨테이너에 맞게 조정할 수 있습니다.
🔹 BoxFit 옵션
| 속성 | 설명 |
|---|
BoxFit.cover | 비율을 유지하면서 컨테이너를 꽉 채움 (잘릴 수 있음) |
BoxFit.contain | 비율을 유지하면서 컨테이너 내부에 맞춤 (잘리지 않음) |
BoxFit.fill | 비율 무시하고 컨테이너 크기에 맞게 이미지 늘림 |
BoxFit.fitWidth | 가로 크기에 맞춰 비율 유지하며 조정 |
BoxFit.fitHeight | 세로 크기에 맞춰 비율 유지하며 조정 |
BoxFit.none | 이미지를 크기 조정하지 않고 원본 크기대로 표시 |
✅ 예제 코드
Image.asset(
'assets/images/sample.jpg',
fit: BoxFit.cover,
width: 200,
height: 200,
)
📌 3-6. 이미지 로딩 처리 (로딩 중/오류 처리)
Image.network(
'https://example.com/sample.jpg',
width: 150,
height: 150,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return Center(child: CircularProgressIndicator());
},
errorBuilder: (context, error, stackTrace) {
return Icon(Icons.error, color: Colors.red);
},
)
📌 정리
| 이미지 타입 | 사용 위젯 | 설명 |
|---|
| 프로젝트 내부 이미지 | Image.asset() | 앱 내부 assets 폴더에서 이미지 로드 |
| 인터넷 이미지 | Image.network() | URL을 통해 이미지 로드 |
| 로컬 저장소 이미지 | Image.file() | 디바이스에서 선택한 이미지 로드 |
| 메모리 이미지 | Image.memory() | 바이트 배열을 이미지로 변환 |
| 네트워크 캐싱 이미지 | CachedNetworkImage() | 인터넷 이미지에 캐싱 적용 |
4. 텍스트 및 스타일링
- Flutter에서 텍스트를 표시하는 기본적인 방법과 스타일을 적용하는 방법을 다룹니다.
- 폰트 크기, 색상, 정렬, 커스텀 폰트 적용 등 다양한 기능을 활용할 수 있습니다.
📌 4-1. 기본 텍스트 표시
- Flutter에서 텍스트를 표시하는 가장 기본적인 방법은
Text 위젯을 사용하는 것입니다.
✅ 예제 코드
Text("안녕하세요, Flutter!",
style: TextStyle(fontSize: 20),
)
🔹 Text 주요 속성
| 속성 | 설명 |
|---|
data | 텍스트 내용 |
style | 텍스트 스타일 지정 (TextStyle) |
textAlign | 텍스트 정렬 (left, center, right) |
maxLines | 최대 줄 수 제한 |
overflow | 글자 초과 시 처리 방식 (ellipsis, fade 등) |
📌 4-2. 텍스트 스타일 적용 (TextStyle)
TextStyle을 사용하면 폰트 크기, 굵기, 색상 등을 설정할 수 있습니다.
✅ 예제 코드
Text("커스텀 스타일 텍스트",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.blue,
letterSpacing: 2.0,
wordSpacing: 5.0,
fontStyle: FontStyle.italic,
),
)
🔹 TextStyle 주요 속성
| 속성 | 설명 |
|---|
fontSize | 폰트 크기 |
fontWeight | 폰트 굵기 (FontWeight.bold 등) |
color | 텍스트 색상 |
letterSpacing | 글자 간격 조절 |
wordSpacing | 단어 간격 조절 |
fontStyle | FontStyle.italic (기울임) |
decoration | 밑줄, 취소선 적용 |
📌 4-3. 여러 스타일 적용 (RichText)
RichText와 TextSpan을 사용하면 한 줄 안에서도 다양한 스타일을 적용할 수 있습니다.
✅ 예제 코드
RichText(
text: TextSpan(
children: [
TextSpan(
text: "굵은 텍스트 ",
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold, color: Colors.black),
),
TextSpan(
text: "빨간색 텍스트",
style: TextStyle(fontSize: 18, color: Colors.red),
),
TextSpan(
text: " 밑줄 텍스트",
style: TextStyle(fontSize: 18, decoration: TextDecoration.underline),
),
],
),
)
📌 4-4. 텍스트 정렬 및 줄바꿈
textAlign을 사용하면 텍스트 정렬을 지정할 수 있습니다.
maxLines와 overflow를 활용하면 긴 텍스트 처리 방식도 조절할 수 있습니다.
✅ 예제 코드
Text(
"Flutter에서 텍스트를 정렬하는 예제입니다.",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
maxLines: 2,
overflow: TextOverflow.ellipsis,
)
🔹 textAlign 옵션
| 값 | 설명 |
|---|
TextAlign.left | 왼쪽 정렬 (기본값) |
TextAlign.center | 중앙 정렬 |
TextAlign.right | 오른쪽 정렬 |
TextAlign.justify | 양쪽 정렬 |
📌 4-5. 커스텀 폰트 적용
- 프로젝트에 원하는 폰트를 추가할 수 있습니다.
- 이때 pubspec.yaml 파일을 수정해야 합니다.
✅ 설정 방법
assets/fonts/ 폴더를 프로젝트 루트에 생성
- 원하는
.ttf 폰트 파일을 추가
pubspec.yaml 수정
flutter:
fonts:
- family: CustomFont
fonts:
- asset: assets/fonts/MyCustomFont.ttf
TextStyle에서 사용
✅ 예제 코드
Text(
"커스텀 폰트 적용",
style: TextStyle(
fontFamily: "CustomFont",
fontSize: 20,
),
)
📌 4-6. 배경색과 함께 텍스트 표시
- 텍스트를 강조하기 위해
Container 또는 DecoratedBox를 사용할 수 있습니다.
✅ 예제 코드
Container(
padding: EdgeInsets.all(10),
color: Colors.yellow,
child: Text(
"배경이 있는 텍스트",
style: TextStyle(fontSize: 18),
),
)
📌 정리
| 기능 | 사용 위젯 | 설명 |
|---|
| 기본 텍스트 표시 | Text() | 기본 텍스트 위젯 |
| 텍스트 스타일 | TextStyle | 폰트 크기, 색상, 굵기, 간격 조절 |
| 여러 스타일 적용 | RichText | 한 문장에서 다양한 스타일 적용 |
| 정렬 및 줄바꿈 | textAlign, overflow | 중앙 정렬, 줄 수 제한 |
| 커스텀 폰트 적용 | fontFamily | 프로젝트 내 폰트 추가 |
| 배경색 적용 | Container, DecoratedBox | 텍스트 배경색 설정 |
5. 인터랙티브 위젯
- Flutter에서는 사용자와 상호작용할 수 있는 다양한 인터랙티브 위젯들을 제공합니다. 이 * 위젯들은 클릭, 드래그, 스와이프 등 사용자의 동작에 반응하는 기능을 제공합니다.
📌 4-1. GestureDetector
- 사용자의 제스처(탭, 드래그, 스와이프 등)를 감지하여 반응하는 위젯입니다.
- 여러 제스처를 처리할 수 있으며,
onTap, onLongPress, onPanUpdate 등 다양한 이벤트를 처리할 수 있습니다.
✅ 예제 코드
GestureDetector(
onTap: () {
print("탭이 감지되었습니다!");
},
onLongPress: () {
print("롱프레스가 감지되었습니다!");
},
child: Container(
color: Colors.blue,
width: 200,
height: 200,
child: Center(child: Text("탭하거나 롱프레스 해보세요")),
),
)
✅ 주요 속성
| 속성 | 설명 |
|---|
onTap | 사용자가 탭할 때 호출 |
onLongPress | 사용자가 길게 누를 때 호출 |
onPanUpdate | 드래그할 때 호출 |
onHorizontalDragUpdate | 수평 드래그할 때 호출 |
onVerticalDragUpdate | 수직 드래그할 때 호출 |
📌 4-2. InkWell
- 터치 효과를 제공하는 위젯입니다.
- 버튼처럼 사용자가 터치할 수 있는 영역에 터치 효과를 추가하여 직관적인 UI를 제공합니다.
✅ 예제 코드
InkWell(
onTap: () {
print("InkWell이 탭되었습니다!");
},
child: Container(
padding: EdgeInsets.all(16.0),
color: Colors.blue,
child: Text(
"클릭해보세요",
style: TextStyle(color: Colors.white),
),
),
)
✅ 주요 속성
| 속성 | 설명 |
|---|
onTap | 사용자가 탭할 때 호출 |
onLongPress | 사용자가 길게 누를 때 호출 |
highlightColor | 터치 시 강조 색상 |
splashColor | 터치 시 물결 효과 색상 |
- Flutter에서 제공하는 기본적인 버튼 위젯입니다.
- 버튼의 디자인, 색상, 크기를 쉽게 변경할 수 있습니다.
- 사용자가 버튼을 클릭할 때 동작을 지정할 수 있습니다.
✅ 예제 코드
ElevatedButton(
onPressed: () {
print("버튼이 클릭되었습니다!");
},
style: ElevatedButton.styleFrom(
primary: Colors.blue,
onPrimary: Colors.white,
),
child: Text("버튼 클릭"),
)
✅ 주요 속성
| 속성 | 설명 |
|---|
onPressed | 버튼이 클릭되었을 때 호출 |
child | 버튼에 표시될 위젯 |
style | 버튼의 스타일 설정 (배경색, 크기 등) |
📌 4-4. Switch
- 토글 버튼으로, 사용자가 상태를 전환할 수 있는 스위치입니다.
true와 false 값을 변경하는 데 사용됩니다.
✅ 예제 코드
bool _isSwitched = false;
Switch(
value: _isSwitched,
onChanged: (bool value) {
setState(() {
_isSwitched = value;
});
print("스위치 값: $_isSwitched");
},
)
✅ 주요 속성
| 속성 | 설명 |
|---|
value | 스위치의 현재 상태 (true or false) |
onChanged | 상태가 변경될 때 호출되는 함수 |
📌 4-5. Slider
- 슬라이더는 사용자가 범위 내에서 값을 선택할 수 있는 위젯입니다.
- 슬라이더의 값은 연속적인 숫자 범위로 설정됩니다.
✅ 예제 코드
double _sliderValue = 0;
Slider(
value: _sliderValue,
min: 0,
max: 100,
onChanged: (double newValue) {
setState(() {
_sliderValue = newValue;
});
},
)
✅ 주요 속성
| 속성 | 설명 |
|---|
value | 현재 슬라이더 값 |
min | 슬라이더의 최소 값 |
max | 슬라이더의 최대 값 |
onChanged | 값이 변경될 때 호출되는 함수 |
📌 4-6. TextField
- 텍스트 입력을 위한 위젯입니다.
- 사용자가 텍스트를 입력하고 변경할 수 있는 필드를 제공합니다.
✅ 예제 코드
TextField(
onChanged: (String text) {
print("입력된 텍스트: $text");
},
decoration: InputDecoration(
labelText: "이름 입력",
border: OutlineInputBorder(),
),
)
✅ 주요 속성
| 속성 | 설명 |
|---|
onChanged | 텍스트가 변경될 때 호출되는 함수 |
controller | 텍스트 필드의 값 관리 |
decoration | 입력 필드의 디자인 (테두리, 레이블 등) |
📌 정리
| 위젯 | 역할 |
|---|
GestureDetector | 다양한 제스처 감지 |
InkWell | 터치 효과 제공 |
ElevatedButton | 기본적인 버튼 |
Switch | 토글 스위치 |
Slider | 슬라이더 |
TextField | 텍스트 입력 필드 |
6. 네비게이션 및 화면 전환
Flutter에서 여러 화면을 이동하는 방법과 네비게이션 관련 위젯들을 다룹니다.
Navigator를 활용하여 화면을 전환하고, BottomNavigationBar 또는 Drawer를 사용해 탭 네비게이션을 구현할 수 있습니다.
📌 6-1. 기본 화면 이동 (Navigator)
Flutter에서는 Navigator를 사용하여 화면을 이동합니다.
✅ 화면 이동 (push)
Navigator.push(
context,
MaterialPageRoute(builder: (context) => SecondScreen()),
);
✅ 현재 화면 닫기 (pop)
Navigator.pop(context);
🔹 Navigator 주요 메서드
| 메서드 | 설명 |
|---|
push | 새로운 화면으로 이동 |
pop | 현재 화면을 닫고 이전 화면으로 돌아감 |
pushReplacement | 현재 화면을 새로운 화면으로 대체 |
pushAndRemoveUntil | 특정 화면까지 모든 화면을 제거하고 이동 |
📌 6-2. 화면 이동 시 데이터 전달
- 화면 이동 시 데이터를 함께 넘길 수 있습니다.
✅ 데이터 전달 (push)
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(data: "Hello!"),
),
);
✅ 데이터 받기
class SecondScreen extends StatelessWidget {
final String data;
SecondScreen({required this.data});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Second Screen")),
body: Center(child: Text("받은 데이터: $data")),
);
}
}
📌 6-3. 동적 라우팅 (onGenerateRoute)
- 앱에서 여러 화면을 동적으로 관리할 수 있습니다.
onGenerateRoute를 사용하면, 미리 설정한 라우트에 따라 자동으로 화면을 전환할 수 있습니다.
✅ 예제 코드
void main() {
runApp(MaterialApp(
initialRoute: '/',
onGenerateRoute: (settings) {
if (settings.name == '/second') {
return MaterialPageRoute(builder: (context) => SecondScreen());
}
return null;
},
));
}
📌 6-4. BottomNavigationBar (하단 탭 네비게이션)
하단 네비게이션 바를 추가하여 여러 화면을 쉽게 이동할 수 있습니다.
✅ 예제 코드
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
final List<Widget> _pages = [HomeScreen(), ProfileScreen(), SettingsScreen()];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: _pages[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), label: '홈'),
BottomNavigationBarItem(icon: Icon(Icons.person), label: '프로필'),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: '설정'),
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
),
);
}
}
📌 6-5. Drawer (사이드 메뉴 네비게이션)
- 앱의 왼쪽에서 열리는 사이드바 메뉴를 추가할 수 있습니다.
✅ 예제 코드
Scaffold(
appBar: AppBar(title: Text("Drawer 예제")),
drawer: Drawer(
child: ListView(
children: [
DrawerHeader(
decoration: BoxDecoration(color: Colors.blue),
child: Text("메뉴", style: TextStyle(color: Colors.white, fontSize: 24)),
),
ListTile(
title: Text("홈"),
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => HomeScreen())),
),
ListTile(
title: Text("설정"),
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => SettingsScreen())),
),
],
),
),
body: Center(child: Text("메인 화면")),
)
📌 정리
| 기능 | 사용 위젯 | 설명 |
|---|
| 기본 화면 이동 | Navigator.push() | 화면 전환 |
| 화면 종료 | Navigator.pop() | 현재 화면 닫기 |
| 데이터 전달 | MaterialPageRoute | 화면 이동 시 데이터 넘기기 |
| 동적 네비게이션 | onGenerateRoute | 라우팅을 동적으로 관리 |
| 하단 탭 | BottomNavigationBar | 하단 네비게이션 추가 |
| 사이드 메뉴 | Drawer | 슬라이드 메뉴 구현 |
7. ListView 위젯을 활용하여 세로 스크롤 달기
📌 ListView
- ListView는 가장 일반적으로 사용되는 스크롤 가능한 위젯입니다.
- ListView를 사용하여 자식 위젯들을 세로 또는 가로 방향으로 스크롤 할 수 있습니다.
📌 사용방법
-
기본적으로 ListView의 children 속성에 위젯들을 나열하여 스크롤 가능한 목록을 만듭니다.
ListView(
padding: const EdgeInsets.all(8),
children: <Widget>[
Container(
height: 50,
color: Colors.amber[600],
child: const Center(child: Text('Entry A')),
),
Container(
height: 50,
color: Colors.amber[500],
child: const Center(child: Text('Entry B')),
),
Container(
height: 50,
color: Colors.amber[100],
child: const Center(child: Text('Entry C')),
),
],
)
-
ListView는 기본적으로 세로 방향으로 스크롤됩니다. 만약 가로 방향으로 스크롤하려면 scrollDirection 속성을 사용하여 Axis.horizontal로 설정할 수 있습니다.
ListView(
scrollDirection: Axis.horizontal,
);
📌 ListView.builder
-
ListView.builder는 자식 위젯들이 동적으로 생성될 때, 즉 동일한 유형의 위젯이 여러 개 필요한 경우 사용합니다. itemCount로 항목 수를 지정하고, itemBuilder로 각 항목을 빌드합니다.
final List<String> entries = <String>['A', 'B', 'C'];
final List<int> colorCodes = <int>[600, 500, 100];
Widget build(BuildContext context) {
return ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
color: Colors.amber[colorCodes[index]],
child: Center(child: Text('Entry ${entries[index]}')),
);
}
);
}
📌 구현
-
RecipePage에서 기존 Column을 ListView로 변경하고, crossAxisAlignment 속성을 제거해야 합니다. 왜냐하면, ListView의 자식 위젯들은 기본적으로 왼쪽 정렬이기 때문입니다.
ListView(
children: <Widget>[
],
);
📌 주의사항:
ListView 위젯을 사용하여 화면이 넘칠 때 (예: RecipeListItem 3개를 출력할 때) 발생하는 overflow 문제를 해결할 수 있습니다. ListView는 스크롤 기능을 제공하므로 화면을 벗어나는 경우에도 스크롤하여 확인할 수 있습니다.