본문 바로가기
Flutter for Beginners

Flutter의 디자인 관련 위젯

by Andrew's Akashic Records 2025. 3. 13.
728x90

Flutter

Flutter의 디자인 관련 위젯

Flutter는 Material Design과 Cupertino(iOS 스타일)을 지원하며, 다양한 디자인 관련 위젯을 제공합니다.
UI를 꾸미고 스타일을 적용하는 데 유용한 주요 위젯을 정리해보겠습니다.

1. 컨테이너 (Container)

Container는 박스(Box) 형태의 UI 요소로, 크기 조정, 배경색, 테두리, 그림자 등을 적용할 수 있습니다.

 

Container(
  width: 200,
  height: 100,
  alignment: Alignment.center,
  decoration: BoxDecoration(
    color: Colors.blue, // 배경색
    borderRadius: BorderRadius.circular(15), // 둥근 모서리
    boxShadow: [
      BoxShadow(
        color: Colors.black26, // 그림자 색상
        blurRadius: 10, // 흐림 정도
        offset: Offset(4, 4), // 그림자의 위치
      ),
    ],
  ),
  child: Text("Hello Flutter", style: TextStyle(color: Colors.white, fontSize: 18)),
)
  • Container는 여러 스타일 속성을 적용할 수 있는 가장 기본적인 위젯!

2. 카드 (Card)

Card는 Material Design 스타일의 카드 UI를 제공하는 위젯입니다.

 

Card(
  elevation: 5, // 그림자 효과
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), // 둥근 모서리
  child: Padding(
    padding: EdgeInsets.all(16),
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        Text("Flutter Card", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
        SizedBox(height: 10),
        Text("이것은 카드 UI입니다."),
      ],
    ),
  ),
)
  • Card는 리스트 항목, 프로필 카드, 제품 정보 등을 표시할 때 유용

3. 리스트 타일 (ListTile)

ListTile은 아이콘, 제목, 부제목을 포함하는 리스트 아이템을 쉽게 만들 수 있는 위젯입니다.

 

ListTile(
  leading: Icon(Icons.person, color: Colors.blue), // 왼쪽 아이콘
  title: Text("홍길동"),
  subtitle: Text("Flutter 개발자"),
  trailing: Icon(Icons.arrow_forward_ios), // 오른쪽 아이콘
  onTap: () {
    print("리스트 아이템 클릭!");
  },
)
  • ListTile은 메뉴 리스트, 연락처 목록, 설정 화면 등에 자주 사용됨

4. 다이얼로그 (AlertDialog & Dialog)

팝업 창을 표시할 때 사용하는 위젯입니다.

 

showDialog(
  context: context,
  builder: (context) {
    return AlertDialog(
      title: Text("알림"),
      content: Text("이것은 알림 메시지입니다."),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context), // 닫기 버튼
          child: Text("닫기"),
        ),
      ],
    );
  },
);
  • AlertDialog는 확인 메시지, 경고창, 사용자 입력 요청 등에 사용

5. 바텀시트 (BottomSheet)

화면 하단에서 올라오는 모달 창을 생성하는 UI 요소입니다.

 

showModalBottomSheet(
  context: context,
  builder: (context) {
    return Container(
      padding: EdgeInsets.all(16),
      height: 200,
      child: Column(
        children: [
          Text("바텀 시트", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          SizedBox(height: 10),
          Text("이것은 바텀 시트입니다."),
        ],
      ),
    );
  },
);
  • BottomSheet는 옵션 메뉴, 공유 기능, 추가 정보 제공 등에 유용

6. 슬라이더 (Slider)

값을 조정하는 슬라이드 바 UI입니다.

 

double _value = 0.5;

Slider(
  value: _value,
  min: 0,
  max: 1,
  divisions: 10,
  label: "${(_value * 100).round()}%",
  onChanged: (newValue) {
    setState(() {
      _value = newValue;
    });
  },
)
  • Slider는 음량 조절, 밝기 조절 등의 UI에서 사용됨

7. 프로그레스 인디케이터 (CircularProgressIndicator & LinearProgressIndicator)

로딩 중임을 나타내는 UI 위젯입니다.

원형 로딩 표시 (CircularProgressIndicator)

CircularProgressIndicator(
  color: Colors.blue,
  strokeWidth: 4.0,
)

직선형 로딩 표시 (LinearProgressIndicator)

LinearProgressIndicator(
  value: 0.5, // 50% 진행
  backgroundColor: Colors.grey[300],
  color: Colors.blue,
)
  • 앱이 데이터를 로드 중일 때 사용자에게 로딩 상태를 표시하는 데 사용됨

8. 이미지 위젯 (Image)

Flutter에서 이미지를 표시하는 다양한 방법을 제공합니다.

네트워크 이미지

Image.network(
  "https://flutter.dev/images/flutter-logo-sharing.png",
  width: 100,
  height: 100,
)

로컬 이미지

Image.asset(
  "assets/images/my_image.png",
  width: 100,
  height: 100,
)
  • Image.network()는 웹에서 이미지를 가져올 때 사용
  • Image.asset()은 앱 내부에 저장된 이미지를 불러올 때 사용

9. 스택 (Stack)

위젯을 겹쳐서 배치할 수 있도록 해주는 레이아웃 위젯입니다.

 

Stack(
  children: [
    Container(
      width: 200,
      height: 200,
      color: Colors.blue,
    ),
    Positioned(
      top: 50,
      left: 50,
      child: Icon(Icons.star, color: Colors.white, size: 50),
    ),
  ],
)
  • Stack은 이미지 위에 텍스트를 올리거나, 버튼을 겹쳐 배치할 때 유용

10. 탭바 (TabBar)

탭을 이용하여 화면을 전환할 수 있도록 해주는 위젯입니다.

 

DefaultTabController(
  length: 2,
  child: Scaffold(
    appBar: AppBar(
      title: Text("탭바 예제"),
      bottom: TabBar(
        tabs: [
          Tab(icon: Icon(Icons.home), text: "홈"),
          Tab(icon: Icon(Icons.settings), text: "설정"),
        ],
      ),
    ),
    body: TabBarView(
      children: [
        Center(child: Text("홈 화면")),
        Center(child: Text("설정 화면")),
      ],
    ),
  ),
)
  • TabBar는 앱에서 여러 화면을 전환할 때 사용

디자인 관련 위젯 비교

위젯 기능
Container 박스 형태의 UI 스타일링 가능
Card Material Design 스타일의 카드 UI
ListTile 리스트 아이템을 쉽게 구현
AlertDialog 알림 메시지 팝업
BottomSheet 화면 하단에서 올라오는 모달 창
Slider 값 조절을 위한 슬라이드 바
ProgressIndicator 로딩 상태 표시 (원형, 직선)
Image 네트워크 또는 로컬 이미지 표시
Stack 위젯을 겹쳐서 배치
TabBar 여러 화면을 전환할 수 있는 탭 UI

디자인 관련 위젯 예제 코드

예제 코드 (main.dart)

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: DesignExampleScreen(),
    );
  }
}

class DesignExampleScreen extends StatefulWidget {
  const DesignExampleScreen({super.key});

  @override
  _DesignExampleScreenState createState() => _DesignExampleScreenState();
}

class _DesignExampleScreenState extends State<DesignExampleScreen> {
  double _sliderValue = 0.5; // 슬라이더 상태 값

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      child: Scaffold(
        appBar: AppBar(
          title: Text("디자인 관련 위젯 예제"),
          bottom: TabBar(
            tabs: [
              Tab(icon: Icon(Icons.home), text: "홈"),
              Tab(icon: Icon(Icons.settings), text: "설정"),
            ],
          ),
        ),
        body: TabBarView(
          children: [
            _buildHomeTab(context),
            _buildSettingsTab(),
          ],
        ),
      ),
    );
  }

  // 홈 탭 UI
  Widget _buildHomeTab(BuildContext context) {
    return ListView(
      padding: EdgeInsets.all(16),
      children: [
        // 1. 카드 위젯
        Card(
          elevation: 5,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
          child: Padding(
            padding: EdgeInsets.all(16),
            child: Column(
              children: [
                Text("카드 위젯", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                SizedBox(height: 10),
                Text("Material Design 스타일의 카드 UI"),
              ],
            ),
          ),
        ),
        SizedBox(height: 10),

        // 2. 리스트 타일
        ListTile(
          leading: Icon(Icons.person, color: Colors.blue),
          title: Text("홍길동"),
          subtitle: Text("Flutter 개발자"),
          trailing: Icon(Icons.arrow_forward_ios),
          onTap: () => _showAlertDialog(context),
        ),
        SizedBox(height: 10),

        // 3. 슬라이더
        Text("슬라이더 값: ${(_sliderValue * 100).toInt()}%"),
        Slider(
          value: _sliderValue,
          min: 0,
          max: 1,
          divisions: 10,
          label: "${(_sliderValue * 100).toInt()}%",
          onChanged: (value) {
            setState(() {
              _sliderValue = value;
            });
          },
        ),
        SizedBox(height: 10),

        // 4. 로딩 인디케이터
        Center(child: CircularProgressIndicator()),

        SizedBox(height: 10),

        // 5. 바텀시트 버튼
        ElevatedButton(
          onPressed: () => _showBottomSheet(context),
          child: Text("바텀시트 열기"),
        ),
      ],
    );
  }

  // 설정 탭 UI
  Widget _buildSettingsTab() {
    return Center(
      child: Text("설정 화면", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
    );
  }

  // 다이얼로그 표시
  void _showAlertDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: Text("알림"),
          content: Text("리스트 아이템을 클릭했습니다."),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: Text("닫기"),
            ),
          ],
        );
      },
    );
  }

  // 바텀시트 표시
  void _showBottomSheet(BuildContext context) {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        return Container(
          padding: EdgeInsets.all(16),
          height: 200,
          child: Column(
            children: [
              Text("바텀시트", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
              SizedBox(height: 10),
              Text("이것은 바텀시트입니다."),
            ],
          ),
        );
      },
    );
  }
}

 

디자인 예제 화면

1. Card (카드 UI)

Card(
  elevation: 5,
  shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
  child: Padding(
    padding: EdgeInsets.all(16),
    child: Column(
      children: [
        Text("카드 위젯", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
        SizedBox(height: 10),
        Text("Material Design 스타일의 카드 UI"),
      ],
    ),
  ),
),
  • Material Design 스타일의 카드 UI 제공
  • 사용 사례: 프로필 카드, 뉴스 카드, 상품 카드

2. ListTile (리스트 아이템)

ListTile(
  leading: Icon(Icons.person, color: Colors.blue),
  title: Text("홍길동"),
  subtitle: Text("Flutter 개발자"),
  trailing: Icon(Icons.arrow_forward_ios),
  onTap: () => _showAlertDialog(context),
),
  • 리스트 아이템을 쉽게 구성할 수 있는 위젯
  • 사용 사례: 연락처 목록, 설정 메뉴, 채팅 리스트

3. AlertDialog (팝업 다이얼로그)

showDialog(
  context: context,
  builder: (context) {
    return AlertDialog(
      title: Text("알림"),
      content: Text("리스트 아이템을 클릭했습니다."),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: Text("닫기"),
        ),
      ],
    );
  },
);
  • 팝업 메시지를 표시하는 다이얼로그
  • 사용 사례: 사용자 확인 메시지, 경고창, 폼 제출 확인

4. BottomSheet (바텀시트)

showModalBottomSheet(
  context: context,
  builder: (context) {
    return Container(
      padding: EdgeInsets.all(16),
      height: 200,
      child: Column(
        children: [
          Text("바텀시트", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
          SizedBox(height: 10),
          Text("이것은 바텀시트입니다."),
        ],
      ),
    );
  },
);
  • 화면 하단에서 올라오는 모달 창 제공
  • 사용 사례: 공유 메뉴, 설정 옵션, 추가 기능 제공

5. Slider (슬라이더)

Slider(
  value: _sliderValue,
  min: 0,
  max: 1,
  divisions: 10,
  label: "${(_sliderValue * 100).toInt()}%",
  onChanged: (value) {
    setState(() {
      _sliderValue = value;
    });
  },
),
  • 값을 조정할 수 있는 슬라이더 UI 제공
  • 사용 사례: 음량 조절, 밝기 조절, 데이터 입력

6. CircularProgressIndicator (로딩 인디케이터)

Center(child: CircularProgressIndicator()),
  • 로딩 중임을 표시하는 인디케이터
  • 사용 사례: 데이터 로딩, 네트워크 요청 대기
728x90