플러터 핵심 기능(위젯과 이미지, 폰트 같은 Asset 이용)

  • Scafold 를 이용한 머티리얼 디자인 
  • 이미지와 폰트 추가
  • 사용자와 상호작용하는 앱 만들기

안드로이드 앱을 개발하려면 구글에서 지정한 디자인 지침이 있습니다. 머티리얼 디자인(material Design). 개발하는 앱의 특별함, 독특한 디자인도 좋지만, 사용자 입장에서 직관적이고 일관된 UI를 제공해야 거부감없이 자연스럽게 이용 가능하기에 플러터는 아래와 같이 머티리얼 디자인 라이브러리를 제공합니다.

import 'package:flutter/material.dart';

플러터 코드의 골격은 아래와 같습니다.

  1. main() 에서 runApp() 으로 StatelessWidget 호출
  2. MyApp(StatelessWidget) 에서 StatefulWidget 호출
  3. MaterialFlutterApp(StatefulWidget) 에서, createState() 호출
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MaterialFlutterApp(),
    );
  }
}

class MaterialFlutterApp extends StatefulWidget {

  @override
  State<MaterialFlutterApp> createState() => _MaterialFlutterApp();
}

class _MaterialFlutterApp extends State<MaterialFlutterApp> {
  @override
  Widget build(BuildContext context) {

    return Scaffold(      
    );
  }
}

Scafold 를 이용한 머티리얼 디자인

위의 위젯을 build 할때, Scafold() 내용의 구조는 아래와 같습니다.

class _MaterialFlutterApp extends State<MaterialFlutterApp> {
  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text('Materail Design App'),
      ),
      floatingActionButton: FloatingActionButton(child: Icon(Icons.add),
        onPressed: () {
        },
      ),
      body: Container(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Icon(Icons.android),
            Text('android')
          ],
        ),
      ),
    );
  }
}

추가로, 아이콘을 직접 제작하기 보다는 기본적으로 제공하는 이미지를 활용하는 것이 좋습니다. 아래의 주소에 들어가시면, 다양한 이미지를 한번에 볼 수 있으니 참고하시기 바랍니다.

https://www.fluttericon.com/

 

FlutterIcon - Flutter custom icons generator

This site will not work if cookies are completely disabled. {"assets_hash":"e63afe94764170521b88e195c1026df9","page_data":{},"locale":"en-US","layout":"fontello.layout"}

www.fluttericon.com

머테리얼 디자인 아이콘 화면

이미지와 폰트 추가

이미지를 화면에 표시하려면 3가지 절차가 있습니다.

  1. 이미지 파일을 프로젝트 바로 아래 폴더를 만들어 이동하기
  2. pubspec.yaml 파일에 리소스 경로 추가하기 
  3. Image.asset(경로) 로 코딩하기

pubspec.yaml 등록시 파일단위로 할 수도 있고, 폴더째로 할 수도 있습니다. 또한 asset/images, images 등 폴더명에 대한 제약사항은 없고 프로젝트 바로 아래에만 생성해 주시면 됩니다. 등록 후, "Pub get", "Pub update" 한번 클릭해주세요.

프로젝트내 image 폴더를 만들어 이미지 추가 및 pubspec.yaml 수정

이미지를 추가하는 방식은 2가지가 있습니다. 프로젝트 내에 있는 asset 항목은 Image.asset으로 외부에 있는 것은 Image.network로 코딩하시면 됩니다. 

body: Container(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image.asset('images/flutter.png'),
            Image.network('https://w7.pngwing.com/pngs/14/381/png-transparent-flag-fluttering-red-flag-miscellaneous-flag-flag-of-india-thumbnail.png')
          ],
        ),
      ),

플러터의 이미지가 보이지 않는다면, 

  1. 코딩할 때, 항목의 경로를 정확하게 오타없이 작성했는지 확인
  2. pubspec.yaml 파일의 오타, 경로 확인 후, "Pub get" 실행
  3. 가상디바이스(Emulator) 재실행

사실 저도 이 포스트를 하면서 이미지가 나오지 않아 1시간 동안 위의 1~2번을 몇번을 했습니다. 폴더가 무조건 asset/images 여야 하나? 파일 단위가 아니라 폴더 단위로 해야 하나? 결국엔 가상디바이스 재실행까지 3번정도 하나가 어느순간 짜자~~~안...ㅠㅠ. 뭐가 문제인지는 정확히 알려나 주지..;;;

플러터의 이미지 크기 조절하는 fit 옵션값들

이미지가 원하는 규격이 아닐 경우, fit 옵션에 따라 아래와 그림과 같이 다양하게 표현할 수 있습니다. 

fit:BoxFit 값에 따른 이미지 표시

fit 옵션값 설명
예제 : Image.asset('images/flutter.png', width:100, height:150, fit:BoxFit.fill); 
BoxFit.fill width, height를 가득 채워서 그림
BoxFit.contain 이미지가 잘리지 않고, 비율을 유지하는 범위에서 가능한 크게 그림
BoxFit.cover 이미지가 잘리더라도, 비율을 유지한채 지정한 범위를 모두 덮도록 그림
BoxFit.none 원본 이미지를 그대로 표시하며, 이미지가 잘릴 수 있음
BoxFit.scaleDown 전체 이미지가 나올 수 있게 이미지 크기를 조절해서 표시
BoxFit.fitWidth width를 꽉 채워서 그림. 이미지가 잘릴 수 있음
BoxFit.fitHeight height를 꽉 채워서 그림. 이미지가 잘릴 수 있음

플러터의 폰트 등록 및 사용하기

pubspec.yaml 에 폰트를 등록한 후 사용합니다. 등록 과정에서 yaml을 탭간격이 띄어쓰기 2칸인데 줄맞춤이 맞질 않거나, 리소스명을 변경했다면, hot-reload가 실패할 경우가 많아 AVD를 재실행해야 합니다. 처음에 한글명을 이용했는데, 스튜디오에서는 인식 과정에 문제는 없었으나, 폰트가 변경되지 않은 것 같아 영문으로 변경하고, AVD 재실행하니 폰트가 변경되었습니다. 

무료 폰트는 인터넷에 검색하면 많이 있습니다. 저는 relation2 라는 사이트에서 무료라인센스로 되어 있는 것은 확인 후 다운 받았습니다. 

flutter:
  uses-material-design: true
  assets:
    - images/flutter.png     #파일 기준
    - images/profile/        #폴더 기준
  fonts:
    - family: strong_army
      fonts:
        - asset: assets/font/strong_army_medium.ttf
          weight: 200 #외곽선에 가중치를 100~900사이로 지정

    - family: kwedustrong
      fonts:
        - asset: assets/font/kwedustrong.ttf
          weight: 700

폰트 스타일을 지정한 코드와 결과 화면

사용자와 상호작용하는 앱만들기

TextEditingController()를 만들어, 공통된 입력값 항목 검증을 수행할 수 있습니다. 이 부분은 소스가 너무 많아, 책을 보고 코딩 연습은 했지만 블로그에는 기재하지 않겠습니다. 아래는 RaisedButton 폐기에 따른 수정 코딩입니다.

Padding(
                  padding: EdgeInsets.all(15),
                  child: ElevatedButton(
                    child: Row(
                      children: <Widget>[
                        Icon(Icons.add),
                        Text('더하기'),
                      ],
                    ),
                    style: ButtonStyle(
                          backgroundColor: MaterialStateProperty.all(Colors.amber)),
                    onPressed: () {

                    },
                  ),
                ),

 

요약
• 안드로이드의 머테리얼 디자인을 이용하기 위해 Scafold라는 큰 틀내에 위젯들을 호출
• pubspec.yaml 파일에 이미지, 폰트 등을 등록한 후, AVD 재실행
• TextEditingController를 이용해서 사용자값을 입력받고, 처리

 

Posted by 목표를 가지고 달린다
,