Flutter 기초

Updated:


1.플로터 앱페이지 기본 코드 이해하기

  • main.dart 의 기본적인 이해 하기
// 필수 material ui package
import 'package:flutter/material.dart';

// futter 에서 최상위에 위치하는 widget 인 runApp() 은 항상 argument 를 widget 를 가져와야 함
void main() => runApp(MyApp());

// MyApp 은 정적인 state 임으로 statelessStatement 로 만들어야 함
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // MaterialApp 이 MyApp 밑에 위치하고 실질적으로 모든 위젯을 감싸는 위젯
    return MaterialApp(
      // 이 타이틀은 App 의 이름을 총칭하는 title
      title: 'First app',
      // ThemData는 app의 기본적인 테마를 지정하는 위젯
      theme: ThemeData(
          // primaryWatch 는 어떠한 특정한 색상을 primeColor 로 지정해서 사용하겠다는 의미를 말함
          // material ui 에서 제공하는 색상 중에서 blue 라는것을 지정
          primarySwatch: Colors.blue),
      // home 은 App 이 정상적으로 실행 되었을때 보여주는 경로임
      home: MyHomePage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    // scaffold 위젯은 화면에 표현할때 최상단 구조 뼈대 위젯을 말함 마치 위젯을 그리기 위한 도화지 같은것임 scaffold 가 없으면 위젯을 그리지 못함
    return Scaffold(
      // 화면의 최상단에 위치되는 위젯인 AppBar
      appBar: AppBar(
        // Text 위젯은 text 를 사용할수 있는 위젯 string 형태로 argument 를 가짐
        // appBar 위에 title 은 화면에 출력되는 title 을 가리킴
        title: Text('First App'),
      ),
      // body 는 scaffold 에서 body 부분을 그릴 수 있는 위젯
      // body 부분에서 중앙에 위치 시킬수 있는 위젯 Center
      body: Center(
        // Center 안에 child 를 가질 수 있는데 Column() 위젯을 가져 올수 있는데 그 안에 모든 요소들을 세로로 배치 할 수 있는 위젯
        child: Column(
          // 요소들을 세로로 배치해야되기 때문에 children 의 list 를 가져옴
          children: <Widget>[
            Text('Hello'),
            Text('Hello'),
            Text('Hello'),
          ],
        ),
      ),
    );
  }
}

image

2.Class 와 Widget

  • Class : 객체가 가져야하는 속성과 기능을 정의한 내용을 담고 있는 설계도 역활

  • Object (객체): class 가 정의된 후 메모리상에 할당되었을 때 이를 객체라고 함

  • Instance: class 기반으로 생성되며, 클래스의 속성과 기능을 똑같이 가지고 있고 프로그래밍 상에서 사용되는 대상임


// class, constructor, instance, widget 에 대한 개념 예시

class Person {
//   class type 선언
  String name;
  int age;
  String sex;

//   Constructor with named argument
//   named 로 만들게 되면 optional 한 argument 값이 되서 입력을 안받아도 됨
//   순서도 상관이 없게 됨
  Person({String name, int age, String sex}) {
    this.name = name;
    this.age = age;
    this.sex = sex;
  }
}

void main() {
//   instance 생성
//   flutter 에서는 아래와같이 widget에서 named argument 형태로 사용함
//   예를 들어 appBar: 위젯명(), body: 위젯명(), 이런식으로 사용함
//   그래서 widget 이 class 인데 사용되는건 constutor 에 생성된 named argument 를 집에 넣어서 instance 형태로 widget 을 사용하는 것임
  Person p1 = Person(age: 30);
  Person p2 = Person(sex: 'male');

  print(p1.age);
}

3.AppBar 메뉴 아이콘 추가하기

  • leading : 아이콘 버튼이나 간단한 위젯을 왼쪽에 배치 할때 사용합니다

  • actions : 복수의 아이콘 버튼 등을 오른쪽에 배치할때 사용합니다

  • onPressed : 함수의 형태로 일반 버튼이나 아이콘 버튼을 터치했을 때 일어나는 이벤트를 정의 하는 곳입니다.

lass MyPage extends StatelessWidget {
  const MyPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Appbar icon Menu'),
        centerTitle: true,
        elevation: 0.0,
        // leading : 위젯이나 아이콘등을 타이틀 왼쪽에 위치 시키는것 (AppBar, ListTile  등에서 사용됨)
        leading: IconButton(
          icon: Icon(Icons.menu),
          // IconButton 을 누르면 실행될 action 함수 설정
          onPressed: () {
            print('Menu button is clicked');
          },
        ),
        actions: [
          IconButton(
            icon: Icon(Icons.shopping_cart),
            onPressed: () {
              print('Shopping cart button is clicked');
            },
          ),
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {
              print('Search button is clicked');
            },
          ),
        ],
      ),
    );
  }
}

image

4.Drawer 메뉴 만들기

  • Drawer 는 햄버거 메뉴 버튼을 누르게 되면 옆에서 창이 나타나면서 추기적인 내용을 작성 할 수 있는 기능을 말합니다. drawer 를 만들게 되면 appBar 시작 부분에 자동으로 햄버거 메뉴가 생성이 됩니다

  • ListView 위젯은 복수의 위젯을 나열하는 위젯리스트가 children 속성을 통해서 호출됩니다. 그 하나하나를 ListTile 이라고 합니다. ListTile 안에는 icon, title, button 등이 사용됩니다

image

drawer: Drawer(
  child: ListView(
    padding: EdgeInsets.zero,
    children: <Widget>[
      UserAccountsDrawerHeader(
        currentAccountPicture: CircleAvatar(
          backgroundImage: AssetImage('assets/sample.png'),
          backgroundColor: Colors.white,
        ),
        // 다른 account 사진 설정
        otherAccountsPictures: const <Widget>[
          CircleAvatar(
            backgroundImage: AssetImage('assets/sample.png'),
            backgroundColor: Colors.white,
          )
        ],
        accountName: Text('Jacob'),
        accountEmail: Text('jacobkosmart@gmail.com'),
        // 디테일 버튼 누르면 실행될 코드
        onDetailsPressed: () {
          print('arrow is clicked');
        },
        // UserAccountDraweHeader 부분 box 크기 조정
        decoration: BoxDecoration(
          color: Colors.lightBlue[200],
          // hearder 밑 부분 라운드 처리
          borderRadius: BorderRadius.only(
            bottomLeft: Radius.circular(40.0),
            bottomRight: Radius.circular(40.0),
          ),
        ),
      ),
      // ListTile
      ListTile(
        leading: Icon(
          Icons.home,
          color: Colors.grey[850],
        ),
        title: Text('Home'),
        onTap: () {
          print('Home is Clicked');
        },
        // leading 과 반대로 뒤에 붙는 trailing
        trailing: Icon(Icons.add),
      ),
      ListTile(
        leading: Icon(
          Icons.settings,
          color: Colors.grey[850],
        ),
        title: Text('Setting'),
        onTap: () {
          print('Setting is Clicked');
        },
        // leading 과 반대로 뒤에 붙는 trailing
        trailing: Icon(Icons.add),
      ),
      ListTile(
        leading: Icon(
          Icons.question_answer,
          color: Colors.grey[850],
        ),
        title: Text('Q&A'),
        onTap: () {
          print('Q&A is Clicked');
        },
        // leading 과 반대로 뒤에 붙는 trailing
        trailing: Icon(Icons.add),
      ),
    ],
  ),
),

Kapture 2021-10-13 at 08 05 50

5. BuildContext

첫번째 정의

  • A handle to the location of a widget in the widget tree : “widget tree 에서 현재 widget 의 위치를 알 수 있는 정보 를 말합니다

  • flutter 의 widget 은 함수 method 인 build method 를 자기고 있습니다. 이것을 통해서 계층구조로 만들어 갑니다 (에, Widget 1 => widget 2 => …)

  • build method 는 scaffold widget 을 return 하는데, widget tree 상에서 어디에서 위치하고 있는지 정보를 가지고 있는 context 라는 것을 넣어서 return 해주는것이라고 보면 됩니다.

두번째 정의

  • Each widget has its own BuildContext, which becomes the parent of the widget returned by the StatelessWidget.build or State.build function : 이 BuildContext 는 stateless 위젯이나 state 빌드 메서드에 의해 리턴된 위젯의 부모가 됩니다

  • 만약 Scaffold() 의 위치가 필요해서, 현재 Scaffold 위젯의 context 를 참조하면 원래 되야 되는데, 참조하게 되면 에러가 발생되는데 "Scaffold.of() called with a context that dose not contain a Scaffold" 라고 에러가 발생됩니다. 왜냐면 context 는 Scaffold 가 widget tree 상에서의 정보를 가지고 있지 않기 때문에 error 가 발생된것입니다.

  • 그래서 해결방법은 Scaffold widget 에 물려받은 위젯의 context 를 가지고 알 수 있게 할 수 있습니다.

스크린샷 2021-10-13 오후 5 06 16

6.Container Widget

  • Containers with no children try to be as big as possible : Container 위젯은 페이지 안에서 최대한의 공간을 차지 하려고 한다는 의미 입니다.

  • Containers with children size themselves to their children. : Container 는 children 을 가지게 되면 그 child 의 크기대로 줄어 든다는 의미 입니다.

  • Container 는 오직 하나만의 child 만 가질 수 있습니다

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Container'),
        centerTitle: true,
      ),
      // safeArea 를 사용해서 화면 밖으로 나가지 않게 하는 widget
      body: SafeArea(
        child: Container(
          // children 이 없을 경우에 screen 전체 화면을 차지함
          color: Colors.red,
          width: 100,
          height: 100,
          // symentric 을 사용하게 되면 상하 값, 좌우 값을 지정함
          margin: const EdgeInsets.symmetric(
            vertical: 50,
            horizontal: 10,
          ),
          //  Continer 안에 포함되는 사이의 거리 값임
          padding: const EdgeInsets.all(40.0),
          // child 가 있을때 Text 의 사이즈 만큼 Container 가 작아짐
          child: Text('Hello'),
        ),
      ),
    );
  }
}

image

7.Column / Row widget

Column

  • Center widget 은 Column 에서 좌우를 조절 해서 center 위치 하지만 상하 mainAxis 방향은 따로 설정을 해줘야 합니다

  • 방법은 mainAxisAlignment: MainAxisAlignment.center, mainAxisSize: MainAxisSize.min, 2 가지 인데 두개는 통제하는 범위에 따라서 쓰임세가 약간 다름니다

mainAxisAlignment: MainAxisAlignment.center

image

mainAxisSize: MainAxisSize.min,

image

verticalDirection

  • verticalDirection 은 children 에 있는 위치를 어디서 부터 하는지를 정하는 위젯입니다. (up 하게 되면 역순으로 밑에서부터 1,2,3 순으로 됨)

image

MainAxisAlignment.spaceEvenly

  • 간격 조정에서 spaceEvenly 는 각 children 의 item 들의 간격을 일정하게 해줍니다.

mainAxisAlignment: MainAxisAlignment.spaceEvenly,

image

MainAxisAlignment.spaceBetween

  • spaceBetween 은 스크린에 상 중 하 에 딱 붙어서 배치하게 됨

mainAxisAlignment: MainAxisAlignment.spaceBetween,

image

MainAxisAlignment.spaceAround

  • spaceAround 은 스크린의 끝부분과 children 사이의 간격 모두 동일하게 위치합니다

image

crossAxisAlignment: CrossAxisAlignment.end

container 를 cross 축으로 최대한 end point 까지 맞추는 설정값 입니다.

Container(
  width: double.infinity,
)

image

crossAxisAlignment: CrossAxisAlignment.stretch,

  • 가로방향으로 꽉 채워주기 위해선 stretch 해주면 각 container 에 상관 없이 가로 옆으로 꽉 차게 됩니다

image

SizedBox

  • Container 사이에 투명 박스를 위치 시켜 개별적으로 container 사이의 간격을 조정할 수 있습니다.
Container(
  width: 100,
  height: 100,
  color: Colors.red,
  child: Text('Container 1'),
),
SizedBox(
  height: 50.0,
),
Container(
  width: 200,
  height: 100,
  color: Colors.yellow,
  child: Text('Container 2'),
),

image

body: Center(
  // Column 에서 center 는 좌우 center 속성만 관여하게 됨
  child: Column(
    // 상하 축 Center 속성을 주기 위해서는 mainAxisAlignment 에서 center 속성을 주어야 함
    // mainAxisAlignment: MainAxisAlignment.center,
    // 상하의 통제권을 같기 위해서는 mainAxisSize 속성을 사용함
    // mainAxisSize: MainAxisSize.min,
    // verticalDirection 은 children 에 있는 위치를 어디서 부터 하는지를 정하는 위젯입
    // verticalDirection: VerticalDirection.up, // up 하게 되면 1이 아래서부터 나열됨
    // 간격 조정에서 spaceEvenly 는 각 children 의 item 들의 간격을 일정하게 해줍니다.
    // spaceBetween 은 스크린에 상 중 하 에 딱 붙어서 배치하게 됨
    // spaceAround 은 스크린의 끝부분과 children 사이의 간격 모두 동일하게 위치합니다
    // mainAxisAlignment: MainAxisAlignment.spaceAround,
    // crossAxisAlignment: CrossAxisAlignment.end,
    // 가로방향으로 꽉 채워주기 위해선 stretch 해주면 각 container 에 상관 없이 가로 옆으로 꽉 차게 됩니다
    crossAxisAlignment: CrossAxisAlignment.stretch,
    children: [
      Container(
        width: 100,
        height: 100,
        color: Colors.red,
        child: Text('Container 1'),
      ),
      SizedBox(
        height: 50.0,
      ),
      Container(
        width: 200,
        height: 100,
        color: Colors.yellow,
        child: Text('Container 2'),
      ),
      SizedBox(
        height: 50.0,
      ),
      Container(
        width: 100,
        height: 100,
        color: Colors.green,
        child: Text('Container 3'),
      ),
      // 끝에 정렬을 맞게 width 를 최대한 크게 하라는 임의의 container 를 만들어 적용하면 오른쪽 끝으로 이동 합니다
      Container(
        width: double.infinity,
      ),
    ],
  ),
),

Row

  • Container 를 가로 축으로 배열하는 위젯 설정 자세한 설정값은 위에 Column 에서 나온 속성들과 방향만 다르시 거의 동일하게 사용됩니다
body: Center(
  child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      Container(
        width: 100,
        height: 100,
        color: Colors.red,
        child: Text('Container 1'),
      ),
      SizedBox(
        width: 30.0,
      ),
      Container(
        width: 100,
        height: 100,
        color: Colors.yellow,
        child: Text('Container 2'),
      ),
      SizedBox(
        width: 30.0,
      ),
      Container(
        width: 100,
        height: 100,
        color: Colors.green,
        child: Text('Container 3'),
      ),
    ],
  ),
),

image

Flutter Layout Cheat Sheet

🔶 🔷 📌 🔑

Reference

Categories:

Updated:

Leave a comment