Flutter 화면 전환

|

Flutter에서 화면 전환을 하는 예제입니다. Navigator를 이용해서 새로운 화면을 push 또는 pop 하여 화면간 전환을 합니다.

main.dart

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerApp());

class SnowDeerApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SnowDeer App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.deepPurple,
      ),
      home: FirstScreenWidget(),
    );
  }
}

class FirstScreenWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Container(
          width: double.infinity,
          height: double.infinity,
          color: Colors.amber,
          child: Center(
              child: RaisedButton(
            child: Text('Move to Second Screen'),
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => SecondScreenWidget()),
              );
            },
          ))),
    );
  }
}

class SecondScreenWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Second Screen'),
      ),
      body: Container(
          width: double.infinity,
          height: double.infinity,
          color: Colors.green,
          child: Center(
              child: RaisedButton(
            child: Text('Back to First Screen'),
            onPressed: () {
              Navigator.pop(context);
            },
          ))),
    );
  }
}


화면간 데이터 전달하는 방법

아래와 같이 사용자 정의 클래스를 만들고 해당 인스턴스를 다음 화면에 전달하는 예제입니다.

class Item {
  int id;
  String name;

  Item({this.id, this.name});
}


전체 코드

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerApp());

class SnowDeerApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'SnowDeer App',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primaryColor: Colors.deepPurple,
      ),
      home: FirstScreenWidget(),
    );
  }
}

class Item {
  int id;
  String name;

  Item({this.id, this.name});
}

class FirstScreenWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Container(
          width: double.infinity,
          height: double.infinity,
          color: Colors.amber,
          child: Center(
              child: RaisedButton(
            child: Text('Move to Second Screen'),
            onPressed: () {
              final item = Item(id: 10, name: 'snowdeer');
              Navigator.push(
                context,
                MaterialPageRoute(
                    builder: (context) => SecondScreenWidget(item: item)),
              );
            },
          ))),
    );
  }
}

class SecondScreenWidget extends StatelessWidget {
  final Item item;

  SecondScreenWidget({this.item});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Second Screen"),
      ),
      body: Container(
          width: double.infinity,
          height: double.infinity,
          color: Colors.green,
          child: Center(
            child: Text('id: ${item.id}, name: ${item.name}'),
          )),
    );
  }
}

위에서 두 번째 위젯인 SecondScreenWidget의 생성자를 통해서 item 인스턴스를 속성에 넣어주도록 했습니다.

생성자는 아래와 같이 필수 입력 매개변수로 선언하면 좀 더 안전한 코드가 됩니다.

SecondScreenWidget({@required this.item});

Flutter Widget을 이용해 로그인 화면 배치해보기

|

로그인 화면 배치

Image

main.dart

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s Login Example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
//            appBar: AppBar(title: Text(title)),
            body: Container(
              margin: EdgeInsets.symmetric(horizontal: 40),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Container(
                    child: Image.asset(
                      'assets/images/snowdeer.png',
                      width: 160,
                      height: 160,
                    ),
                  ),
                  Container(
                      margin: EdgeInsets.only(top: 20),
                      child: TextFormField(
                        keyboardType: TextInputType.emailAddress,
                        initialValue: 'snowdeer0314@gmail.com',
                        decoration: InputDecoration(
                          border: OutlineInputBorder(),
                        ),
                      )),
                  Container(
                      margin: EdgeInsets.only(top: 8),
                      child: TextFormField(
                        obscureText: true,
                        decoration: InputDecoration(
                          border: OutlineInputBorder(),
                          hintText: 'Input password',
                        ),
                      )),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      RaisedButton(
                        child: Text("Login"),
                        onPressed: () => {print("LoginButton is Clicked.")},
                      ),
                      SizedBox(
                        width: 8,
                      ),
                      RaisedButton(
                        child: Text("Cancel"),
                        onPressed: () => {print("CancelButton is Clicked.")},
                      )
                    ],
                  )
                ],
              ),
            )));
  }
}

Flutter ListView Widget 예제

|

ListView Widget 예제

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s ListView Example';
  static const List list = [
    'snowdeer',
    'ran',
    'song',
    'yang',
    'john',
    'downy',
    'gap',
    'kyu',
    'ho',
    'hoon',
  ];

  Widget buildListView() {
    return ListView.builder(
        itemCount: list.length,
        itemBuilder: (BuildContext context, int i) {
          return ListTile(
            title: Text(
              list[i],
            ),
            trailing: Icon(Icons.favorite_border),
          );
        });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
          appBar: AppBar(title: Text(title)),
          body: buildListView(),
        ));
  }
}

Flutter Layout Widget 예제(Container, Row, Column)

|

Container Widget 예제

Container 위젯은 자식을 1개를 갖는 위젯입니다.

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s Container Example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  Container(
                    child: Text('첫 번째 Container'),
                    color: Colors.yellow,
                  ),
                  Container(
                    child: Text('두 번째 Container with padding(EdgeInsets.only)'),
                    padding: EdgeInsets.only(
                        left: 12, top: 12, bottom: 12, right: 12),
                    color: Colors.blueGrey,
                  ),
                  Container(
                    child: Text(
                        '세 번째 Container with padding(EdgeInsets.symmetric)'),
                    padding: EdgeInsets.symmetric(vertical: 12, horizontal: 20),
                    color: Colors.deepOrange,
                  ),
                  Container(
                    child: Text(
                        '네 번째 Container with margin(EdgeInsets.symmetric)'),
                    margin: EdgeInsets.symmetric(vertical: 12, horizontal: 20),
                    color: Colors.cyan,
                  ),
                ])));
  }
}


Row/Column Widget 예제

Row 위젯은 자식 위젯들을 가로로 배치할 때 사용합니다. 반대로 Column은 자식 위젯들을 세로로 배치할 때 사용합니다.

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s Row Example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Container(
                    child: Text('첫 번째 Container'),
                    color: Colors.yellow,
                  ),
                  Container(
                    child: Text('두 번째 Container with padding(EdgeInsets.only)'),
                    padding: EdgeInsets.only(
                        left: 12, top: 12, bottom: 12, right: 12),
                    color: Colors.blueGrey,
                  ),
                  RaisedButton(
                    child: Text('Hello'),
                  )
                ])));
  }
}


Row/Column Widget 속성

RowColumn은 레이아웃 위젯이다보니 중요한 속성들이 있습니다. mainAxisAlignment는 현재 속성의 축(axis)을 기준으로 정렬을 하는 옵션입니다. 현재 레이아웃이 Row이면, 가로 방향을 의미하기 때문에 좌/우 정렬값을 의미합니다. MainAxisAlignment.start, MainAxisAlignment.center 등의 값을 가질 수 있습니다.

crossAxisAlignment는 현재 속성의 반대 방향으로 정렬을 의미합니다.

예를 들어 아래 속성이면 다음 그림과 같이 위젯이 배치됩니다.

  body: Column(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.end,
    ...

Image


  body: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    crossAxisAlignment: CrossAxisAlignment.start,
    ...

Image


  body: Column(
    mainAxisAlignment: MainAxisAlignment.end,
    crossAxisAlignment: CrossAxisAlignment.start,
    ...

Image


  body: Row(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.end,
    ...

Image


  body: Row(
    mainAxisAlignment: MainAxisAlignment.start,
    crossAxisAlignment: CrossAxisAlignment.center,
    ...

Image

Flutter Widget 예제(Text, Image, RaisedButton)

|

Text Widget 예제

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s Text Example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Column(children: [
              Text('안녕하세요. SnowDeer 입니다.'),
              Text('이건 Styled Text 입니다.',
                  style: TextStyle(
                      color: Colors.blue,
                      fontSize: 16.0,
                      fontWeight: FontWeight.bold)),
              Text('이건 두번 째 Styled Text 입니다.',
                  style: TextStyle(
                    color: Colors.white,
                    fontSize: 20.0,
                    fontWeight: FontWeight.bold,
                    background: Paint()
                      ..color = Colors.blueGrey
                      ..style = PaintingStyle.fill,
                  ))
            ])));
  }
}


Image Widget 예제

먼저 이미지 파일을 assets/images 디렉토리에 복사한 다음, pubspec.yaml 파일을 다음과 같이 수정합니다.

flutter:

  uses-material-design: true
  assets:
     - assets/images/

  ...

그 이후 예제 코드는 다음과 같습니다.

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s Image Example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Column(children: [
              Image.asset('assets/images/snowdeer.png')
            ])));
  }
}


RaisedButton Widget 예제

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s RaisedButton Example';

  void onClicked() {
    print('onClicked !!!');
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  RaisedButton(
                    child: Text('Normal Button'),
                    onPressed: onClicked,
                  ),
                  RaisedButton(
                      child: Text('Round Shape Button'),
                      onPressed: onClicked,
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(12),
                      ))
                ])));
  }
}


TextFormField Widget 예제

import 'package:flutter/material.dart';

void main() => runApp(SnowDeerExample());

class SnowDeerExample extends StatelessWidget {
  static const title = 'SnowDeer\'s TextFormField Example';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: title,
        debugShowCheckedModeBanner: false,
        home: Scaffold(
            appBar: AppBar(title: Text(title)),
            body: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: [
                  TextFormField(),
                  TextFormField(
                    keyboardType: TextInputType.number,
                  ),
                  TextFormField(
                    keyboardType: TextInputType.emailAddress,
                  )
                ])));
  }
}

이 때, TextFormField에서 가질 수 있는 키보드 속성은 다음과 같습니다.

  • TextInputType.datetime
  • TextInputType.emailaddress
  • TextInputType.multiline
  • TextInputType.number
  • TextInputType.phone
  • TextInputType.text
  • TextInputType.url