Dandy Now!
  • [Flutter] "Do it! 플러터 앱 프로그래밍" - 플러터 위젯 사용법 | Material 디자인, image와 font 삽입, 사용자와 상호작용
    2022년 02월 11일 13시 50분 14초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    플러터 위젯 사용법

    "조준수. (2021). Do it! 플러터 앱 프로그래밍. 이지스퍼블리싱", 4장을 공부하였다. Material 디자인이 무엇이며 Scaffold를 이용해 어떻게 적용하는지, image와 font를 어떻게 삽입하는지, 사용자와의 상호작용을 위해 입력받는 방법은 무엇이며 어떻게 사용하는지에 대해 학습할 수 있었다.   

     

    Do it! 플러터 앱 프로그래밍

    플러터 기본 & 고급 위젯은 물론오픈 API와 파이어베이스를 이용한 앱 개발부터 배포까지!플러터 SDK 2.x 버전을 반영한 개정판!이 책은 플러터의 기초부터 고급 활용법까지 다루어 다양한 영역에

    book.naver.com

     

    Scaffold를 이용한 Material 디자인 적용

    머티리얼 디자인은 구글에서 2014년부터 사용한 플랫 디자인 지침이다. 간결한 디자인으로 앱의 성능 향상과 일관된 UX의 이점을 갖게 되었다.

    // main.dart
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Material Flutter App',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: MaterialFlutterApp(),
        );
      }
    }
    
    class MaterialFlutterApp extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _MaterialFlutterApp();
      }
    }
    
    // 스테이트풀 위젯을 화면에 출력하기 위해 State 클래스 상속
    class _MaterialFlutterApp extends State<MaterialFlutterApp> {
      @override
      Widget build(BuildContext context) {
        // 머티리얼 디자인을 적용하기 위해서 Scaffold 클래스 이용
        return Scaffold(
          // 제목 줄 추가
          appBar: AppBar(
            title: Text('Material Design App'),
          ),
          // 플로팅 버튼 생성(떠 있는 듯한 버튼)
          floatingActionButton: FloatingActionButton(
            child: Icon(Icons.add),
            onPressed: () {},
          ),
          //
          body: Container(
              // 가로 정열(가운데)
              child: Center(
                // 여러 개의 위젯을 만들려면 Row(가로 배치), Column(세로 배치) 위젯 사용한다.
                child: Column(
                  // children 이용해 배열 형태로 선언한다. 배열 안에 여러 개의 위젯을 담을 수있다.
                  children: <Widget>[
                    Icon(Icons.android), 
                    Text('android')],
                  // 세로 정열(가운데)
                  mainAxisAlignment: MainAxisAlignment.center,
                ),
              )
          ),
        );
      }
    }

     

    [그림 1] Material Design

     


     

    image와 font 추가

    별도의 imageWidget.dart 파일을 생성하고 main.dart에서 import한다. pubspec.yaml 파일에서 image, font과련하여 수정해야 한다. BoxFit 옵션도 잘 봐 두자!

    // main.dart
    import 'package:flutter/material.dart';
    import 'imageWidget.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Matterial Flutter App',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: ImageWidgetApp(), // imageWidget.dart 파일의 ImageWidgetApp 클래스를 호출한다.
        );
      }
    }

     

    // imageWidget.dart
    import 'package:flutter/material.dart';
    
    class ImageWidgetApp extends StatefulWidget {
      @override
      _ImageWidgetAppState createState() => _ImageWidgetAppState();
    }
    
    class _ImageWidgetAppState extends State<ImageWidgetApp> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Image Widget'),
          ),
          body: Container(
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                // 이미지 추가 위해 pubspec.yaml을 수정해야 한다.
                // ---- pubspec.yaml 수정 ----
                // flutter:
                // uses-material-design: true
                // assets:
                //   - image/
                // ---------------------------
                // 이미지 추가 및 설정
                children: [
                  Image.asset(
                    'image/profile.jpg',
                    width: 200,
                    height: 100,
                    fit: BoxFit.contain, // 설정한 width, height에 맞게 크기 조정
                    // ---------------- BoxFit 옵션값 ---------------------
                    // fill: width, height를 가득 채움, 비율 유지 안함
                    // contain: 이미지 안 잘리는 최대 크기, 비율 유지
                    // cover: 이미지 잘리는 최대 크기, 비율 유지
                    // fitWidth: width를 가득 채우며 이미지가 잘림, 비율 유지
                    // ----------------------------------------------------
    
                    // 폰트 추가 위해 pubspec.yaml을 수정해야 한다. font파일은 영어만 가능하다.
                    // ----------- pubspec.yaml 수정 -----------
                    // fonts:
                    // - family: ENBERNF
                    //   fonts:
                    //     - asset: fonts/ENBERNF.ttf
                    //       weight: 400
                    // -----------------------------------------
                  ),
                  // 폰트 추가 및 설정
                  Text(
                    'Hello Flutter',
                    style: TextStyle(
                        fontFamily: 'ENBERNF', fontSize: 50, color: Colors.grey),
                  )
                ],
              ),
            ),
          ),
        );
      }
    }

     

    [그림 2] Image와 Font 추가

     


     

    사용자와 상호작용(Calculator Example)

    사용자로부터 값을 입력받아 처리 및 출력한다. 연산은 onPressed 쪽에 들어간다. initState, TextField(TextInputType), DropdownButton을 잘 봐 두자!

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      static const String _title = 'Widget Example';
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: _title,
          home: WidgetApp(),
        );
      }
    }
    
    // Column을 이용할 수 있게 StatefulWidget을 만든다.
    class WidgetApp extends StatefulWidget {
      @override
      _WidgetExampleState createState() => _WidgetExampleState();
    }
    
    class _WidgetExampleState extends State<WidgetApp> {
      // 두 수를 입력받아서 덧셈 후 그 결과를 출력하는 기능
      String sum = '';
      TextEditingController value1 = TextEditingController();
      TextEditingController value2 = TextEditingController();
      // ------------------------- DropDownButton 관련 ----------------------------
      // _buttonList 리스트 선언
      List _buttonList = ['더하기', '빼기', '곱하기', '나누기'];
      // DropdownButton 형식의 리스트 선언
      List<DropdownMenuItem<String>> _dropDownMenuItems =
          new List.empty(growable: true);
      String? _buttonText;
    
      // 상태를 초기화
      @override
      void initState() {
        super.initState();
        for (var item in _buttonList) {
          _dropDownMenuItems.add(DropdownMenuItem(value: item, child: Text(item)));
        }
        _buttonText = _dropDownMenuItems[0].value;
      }
      // ---------------------------------------------------------------------------
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Calculator Example'),
          ),
          body: Container(
            child: Center(
              child: Column(
                children: <Widget>[
                  // Padding을 주어서 위젯 간에 간격을 만든다.
                  Padding(
                    padding: EdgeInsets.all(15),
                    child: Text(
                      'Flutter',
                      style: TextStyle(fontSize: 20, color: Colors.purple),
                    ),
                  ),
                  // 두 수를 입력 받을 TextField
                  Padding(
                    padding: EdgeInsets.only(left: 20, right: 20),
                    child: TextField(
                        // ---------- TextInputType의 키보드 타입 --------------
                        // text : 기본 텍스트
                        // multiline : 멀티 라인 텍스트. 여러 줄을 입력할 때 사용
                        // number : 숫자 키보드 표시
                        // phone : 전화번호 전용 키보드
                        // datetime : 날짜 입력 키보드
                        // emailAddress : @ 표시 등 이메일 입력 키보드
                        // url : 주소 입력 창
                        // ----------------------------------------------------
                        keyboardType: TextInputType.number,
                        controller: value1),
                  ),
                  Padding(
                    padding: EdgeInsets.only(left: 20, right: 20),
                    child: TextField(
                        keyboardType: TextInputType.number, controller: value2),
                  ),
                  Padding(
                    padding: EdgeInsets.all(15),
                    child: ElevatedButton(
                      child: Row(
                        children: <Widget>[
                          Icon(Icons.add),
                          // Text('더하기'),
                          Text(_buttonText!) // 사용자가 선택한 값
                        ],
                      ),
                      style: ButtonStyle(
                          backgroundColor:
                              MaterialStateProperty.all(Colors.purple)),
                      // 더하기 onPressed 이벤트 처리
                      onPressed: () {
                        setState(() {
                          // TextField에 입력된 모든 데이터는 문자열로 인식되기 때문에 double.parse하여 실수로 변환한다.
                          var value1Int = double.parse(value1.value.text);
                          var value2Int = double.parse(value2.value.text);
                          var result;
                          if (_buttonText == '더하기') {
                            result = value1Int + value2Int;
                          } else if (_buttonText == "빼기") {
                            result = value1Int - value2Int;
                          } else if (_buttonText == "곱하기") {
                            result = value1Int * value2Int;
                          } else {
                            result = value1Int / value2Int;
                          }
                          // TextField에 입력된 모든 데이터는 문자열로 인식되기 때문에 int.parse하여 정수로 변환한다.
                          // int result = int.parse(value1.value.text) +
                          //     int.parse(value2.value.text);
                          sum = '$result';
                        });
                      },
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.all(15),
                    child: Text(
                      '결과 : $sum',
                      style: TextStyle(fontSize: 20),
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.all(15),
                    // 펼침 버튼 생성(items는 펼침 버튼에 표시할 아이템 목록, onChanged는 아이템이 바뀔 때 처리할 이벤트)
                    child: DropdownButton(
                        items: _dropDownMenuItems,
                        onChanged: (String? value) {
                          setState(() {
                            _buttonText = value;
                          });
                        },
                        value: _buttonText),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }

     

    [그림 3] Calculator Example

     

    728x90
    반응형
    댓글