[Flutter 입문] 기본 레이아웃 구성(1): UI 구성

김동연·2025년 3월 27일

1. UI 구성 (User Interface)

1. 기본 레이아웃 구조

  • Flutter에서 UI를 구성할 때 가장 기본이 되는 개념은 위젯 트리입니다.

  • 모든 화면 요소는 위젯으로 구성되며, 부모-자식 관계를 통해 화면이 구조화됩니다.

  • 아래와 같이 화면의 구성요소를 나누고 각각의 요소들을 위젯으로 나누어 컴포넌트합니다.

컴포넌트화

  • 화면을 구성하는 요소를 여러 블록으로 쪼개서 컴포넌트(화면을 구성하는 각 부분)로 만드는 작업


  • Flutter에서 UI를 배치할 때 사용하는 주요 레이아웃 위젯을 정리하면 다음과 같습니다.

📌 1-1. Column (세로 정렬)

  • 위젯들을 세로(위→아래)로 배치할 때 사용합니다.
  • 자식 위젯들은 children 리스트에 추가합니다.
  • mainAxisAlignmentcrossAxisAlignment를 이용해 정렬을 조정할 수 있습니다.

✅ 예제 코드

Column(
  mainAxisAlignment: MainAxisAlignment.center,  // 세로축 기준 중앙 정렬
  crossAxisAlignment: CrossAxisAlignment.start, // 가로축 기준 왼쪽 정렬
  children: [
    Text("첫 번째 아이템"),
    Text("두 번째 아이템"),
    Text("세 번째 아이템"),
  ],
)

✅ 주요 속성

속성설명
mainAxisAlignment세로 방향 정렬 방식 (start, center, end, spaceAround, spaceBetween, spaceEvenly)
crossAxisAlignment가로 방향 정렬 방식 (start, center, end, stretch)
mainAxisSizeColumn의 크기 조절 (max: 가능한 모든 공간 차지, min: 내용만큼 크기 조절)

📌 1-2. Row (가로 정렬)

  • 위젯들을 가로(왼쪽→오른쪽)로 배치할 때 사용합니다.
  • Column과 사용법이 거의 동일하지만, mainAxisAlignmentcrossAxisAlignment의 기준이 가로축과 세로축으로 바뀜에 주의해야 합니다.

✅ 예제 코드

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 위젯

  • AppBarScaffold의 상단에 배치되는 위젯으로, 보통 앱의 제목, 아이콘, 검색 기능 등을 포함하여 네비게이션을 지원합니다.
  • AppBarleading, 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: () {},
    ),
  ],
)

✅ 주요 속성

속성설명
titleAppBar에 표시할 주 제목을 설정합니다.
leadingAppBar의 왼쪽에 위치하는 위젯을 설정합니다 (예: 메뉴 아이콘).
actionsAppBar의 오른쪽에 위치하는 위젯들을 리스트로 추가합니다 (예: 아이콘 버튼들).
flexibleSpaceAppBar의 배경에 고정되지 않은 영역으로, 원하는 레이아웃을 추가할 수 있습니다.
bottomAppBar 아래에 위치하는 위젯을 설정합니다 (예: 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,  // 전체 공간의 2배 차지
      child: Container(color: Colors.red, height: 100),
    ),
    Expanded(
      flex: 1,  // 전체 공간의 1배 차지
      child: Container(color: Colors.blue, height: 100),
    ),
  ],
)

📌 1-6. SizedBox (고정 크기의 빈 공간 추가)

  • 특정 크기의 빈 공간을 만들거나, 위젯의 크기를 제한하는 데 사용됩니다.
  • widthheight 값을 지정하면 해당 크기만큼의 공간을 차지합니다.

✅ 예제 코드

Column(
  children: [
    Text("첫 번째 텍스트"),
    SizedBox(height: 20), // 20px 간격 추가
    Text("두 번째 텍스트"),
  ],
)

📌 1-7. Spacer (균등한 간격 조절)

  • RowColumn에서 위젯 간의 간격을 균등하게 분배할 때 사용됩니다.
  • 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),  // 모든 방향으로 16px 패딩 추가
  child: Text("패딩이 적용된 텍스트"),
)

🔹 주요 속성

속성설명
EdgeInsets.all(값)모든 방향에 동일한 여백 추가
EdgeInsets.symmetric(horizontal: 값, vertical: 값)가로/세로 여백 개별 설정
EdgeInsets.only(left: 값, right: 값, top: 값, bottom: 값)특정 방향에만 여백 추가

📌 2-2. Margin (외부 여백 추가)

  • 위젯 바깥쪽의 여백(마진)을 추가할 때 사용됩니다.
  • 마진은 Containermargin 속성으로 설정할 수 있습니다.

예제 코드

Container(
  margin: EdgeInsets.all(20.0),  // 모든 방향에 20px 마진 추가
  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,  // 16:9 비율 적용
  child: Container(color: Colors.blue),
)

📌 정리

위젯역할
Padding내부 여백 추가
Margin외부 여백 추가
Alignment특정 위치로 정렬
Center중앙 정렬
Container스타일 적용 가능한 박스
AspectRatio특정 비율 유지

3. 이미지 및 리소스 관리

  • Flutter에서 이미지를 불러오는 방식에는 프로젝트 내부 이미지, 인터넷 이미지, 디바이스 저장소 이미지 등이 있습니다.
  • 각 방식별로 사용하는 위젯과 예제를 정리했습니다.

📌 3-1. 프로젝트 내부 이미지 (Asset Image)

앱 내부에 포함된 이미지를 표시할 때 사용됩니다.
이 경우, pubspec.yaml 파일에 이미지 경로를 등록해야 합니다.

설정 방법

  1. assets/ 폴더를 프로젝트 루트에 생성
  2. pubspec.yaml 파일에 아래 내용 추가
flutter:
  assets:
    - assets/images/logo.png
  1. 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);
    });
  }
}


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. 이미지 로딩 처리 (로딩 중/오류 처리)

  • 이미지를 로드할 때 로딩 중 상태나 오류 발생 시 대체 이미지를 표시할 수 있습니다.

  • loadingBuildererrorBuilder를 사용하여 로딩과 오류 처리를 할 수 있습니다.

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단어 간격 조절
fontStyleFontStyle.italic (기울임)
decoration밑줄, 취소선 적용

📌 4-3. 여러 스타일 적용 (RichText)

  • RichTextTextSpan을 사용하면 한 줄 안에서도 다양한 스타일을 적용할 수 있습니다.

✅ 예제 코드

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을 사용하면 텍스트 정렬을 지정할 수 있습니다.
  • maxLinesoverflow를 활용하면 긴 텍스트 처리 방식도 조절할 수 있습니다.

✅ 예제 코드

Text(
  "Flutter에서 텍스트를 정렬하는 예제입니다.",
  textAlign: TextAlign.center,  // 중앙 정렬
  style: TextStyle(fontSize: 18),
  maxLines: 2,                  // 최대 2줄까지 표시
  overflow: TextOverflow.ellipsis, // 초과 시 '...' 표시
)

🔹 textAlign 옵션

설명
TextAlign.left왼쪽 정렬 (기본값)
TextAlign.center중앙 정렬
TextAlign.right오른쪽 정렬
TextAlign.justify양쪽 정렬

📌 4-5. 커스텀 폰트 적용

  • 프로젝트에 원하는 폰트를 추가할 수 있습니다.
  • 이때 pubspec.yaml 파일을 수정해야 합니다.

✅ 설정 방법

  1. assets/fonts/ 폴더를 프로젝트 루트에 생성
  2. 원하는 .ttf 폰트 파일을 추가
  3. pubspec.yaml 수정
flutter:
  fonts:
    - family: CustomFont
      fonts:
        - asset: assets/fonts/MyCustomFont.ttf
  1. 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터치 시 물결 효과 색상

📌 4-3. ElevatedButton

  • Flutter에서 제공하는 기본적인 버튼 위젯입니다.
  • 버튼의 디자인, 색상, 크기를 쉽게 변경할 수 있습니다.
  • 사용자가 버튼을 클릭할 때 동작을 지정할 수 있습니다.

✅ 예제 코드

ElevatedButton(
  onPressed: () {
    print("버튼이 클릭되었습니다!");
  },
  style: ElevatedButton.styleFrom(
    primary: Colors.blue, // 배경색
    onPrimary: Colors.white, // 글자색
  ),
  child: Text("버튼 클릭"),
)

✅ 주요 속성

속성설명
onPressed버튼이 클릭되었을 때 호출
child버튼에 표시될 위젯
style버튼의 스타일 설정 (배경색, 크기 등)

📌 4-4. Switch

  • 토글 버튼으로, 사용자가 상태를 전환할 수 있는 스위치입니다.
  • truefalse 값을 변경하는 데 사용됩니다.

✅ 예제 코드

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});

  
  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 {
  
  _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;
    });
  }

  
  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를 사용하여 자식 위젯들을 세로 또는 가로 방향으로 스크롤 할 수 있습니다.

📌 사용방법

  • 기본적으로 ListViewchildren 속성에 위젯들을 나열하여 스크롤 가능한 목록을 만듭니다.

    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에서 기존 ColumnListView로 변경하고, crossAxisAlignment 속성을 제거해야 합니다. 왜냐하면, ListView의 자식 위젯들은 기본적으로 왼쪽 정렬이기 때문입니다.

    ListView(
      children: <Widget>[
        // ListView 자식 위젯들
      ],
    );

📌 주의사항:

  • ListView 위젯을 사용하여 화면이 넘칠 때 (예: RecipeListItem 3개를 출력할 때) 발생하는 overflow 문제를 해결할 수 있습니다. ListView는 스크롤 기능을 제공하므로 화면을 벗어나는 경우에도 스크롤하여 확인할 수 있습니다.

0개의 댓글