본문 바로가기

Flutter

Flutter 기본예제

전체코드

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run".
        // You'll see the application has a blue toolbar. Then, without quitting the app,
        // try changing the primarySwatch below to Colors.blue and then invoke "hot reload"
        // (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application is not restarted.
        primarySwatch: Colors.blue,
        // This makes the visual density adapt to the platform that you run the app on.
        // For desktop platforms, the controls will be smaller
        // and closer together (more dense) than on mobile platforms.
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application.
  // It is stateful, meaning that it has a State object (defined below)
  // that contains fields that affect how it looks.

  // This class is the configuration for the state.
  // It holds the values (in this case the title) provided by the parent(in this case the App widget)
  // and used by the build method of the State. Fields in a Widget subclass are always marked "final".

  final String title;

  //실행시킬 위젯
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

//기본 위젯
class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has changed in this State,
      // which causes it to rerun the build method below
      // so that the display can reflect the updated values.
      // If we changed _counter without calling setState(),
      // then the build method would not be called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called,
    // for instance as done by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods fast,
    // so that you can just rebuild anything
    // that needs updating rather than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object
        // that was created by the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget.
        // It takes a single child and positions it in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and arranges them vertically.
          // By default, it sizes itself to fit its children horizontally,
          // and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console,
          // choose the "Toggle Debug Paint" action from the Flutter Inspector in Android Studio,
          // or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control
          // how it sizes itself and how it positions its children.
          // Here we use mainAxisAlignment to center the children vertically;
          // the main axis here is the vertical axis because Columns are vertical
          // (the cross axis would be horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

** 해당 클래스(Widget) 의 요소를 확인하고 싶다면 각 클래스(Widget)에 커서를 두고 cmd + B (Window는 Ctrl + B) 를 눌러 정의부분을 확인해 보자.**

**Flutter는 접근제한자가 '_' 이다. '_'로 시작하는 모든 명칭은 private를 의미하고 _가없다면 자동으로 public이 된다. (ex) int _counter의 경우 타 객체지향언어에서 private int counter 이다)**

실행순서 : void main() > class MyApp (Widgt build) > class MyHomePage (_MyHomePageState createState) > class _MyHomePageState

 

main, MyApp _ 시작

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

dart file을 실행할 때 가장먼저 호출되는 함수는 main 함수이다. main 에서 runApp을 통해 MyApp을 실행하게되고 MyApp은 StatelessWidget으로 상태의 변화를 인지할 필요가 없는 Widget으로 변화를 감지하지 않고 한번만 build한다. 가장 기본적인 App widget인 MaterialApp을 생성하는데 MaterialApp이란 여러 위젯을 편리하게 묶어주는 Material 디자인을 사용하는 application 이지만... 우리는 home요소에 할당된 MyHomePage 라는 Widget을 생성한다는 것만 알면 된다. (title, theme는 home요소에 할당된 Widget에서 해당 요소를 따로 지정하지 않을 때 기본적으로 들어가게 되는 default 비슷하다고 생각하면 됨)

(cmd + B) MaterialApp의 요소들

 

MyHomePage _ 변화를 출력하기 위한 준비

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

StatefulWidget은 변화를 감지할 수 있는 Widget으로 흔히 사용자의 동작에 의해 바뀌는 것들을 화면에 바로 적용시켜야 할 때 사용한다. MaterialApp의 home요소에서 'Flutter Demo Home Page' 를 생성자에 전해주었기 때문에 title = 'Flutter Demo Home Page' 로 초기화 되고 _MyHomePageState 를 호출한다. (**StatefulWidget은 반드시 createState()를 override해야 한다)

 

_MyHomePageState _ 실제 App 구현

class _MyHomePageState extends State<MyHomePage> {
  ...
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      ...
    );
  }
}

실제 App이 구현되는 부분은 Widget build(BuildContext context) 다. 이 함수는 Widget이 호출되면 자동으로 호출되는 함수로 예제에서는 바로 Scaffold를 return 한다.

Scaffold

(cmd + B) Scaffold의 요소들

Scaffold는 아마 가장 많이 사용하게 되는 Widget일 것이다. appBarbody 요소는 거의 필수로 개발자가 구현한다.

- appBar

 appBar 요소는 앱에서 상단에 보여주는 Bar를 생성하며 대부분 AppBar Widget을 많이 사용한다. 예제에서는 title에 Text만 지정해 주었다. (**Text(widget.title)에서 widget은 "State<T>" 가 가지고 있는 "T widget" 변수다. 따라서 예제에서는 MyHomePage Widget이고 앞서 title에 'Flutter Demo Home Page' 를 전해주었으므로 title: Text(widget.title) = title: Text('Flutter Demo Home Page') 이다.)

- body

 구현이 필요한 대부분의 요소들은 반환값으로 Widget 1개를 기대한다. "appBar: AppBar" 에서 AppBar, "body: Center" 에서 Center 도 Widget이다. 대부분의 Widget은 요소로서 child 혹은 children을 가지는데 Widget안에 다른 Widget을 구현하고 싶다면 이 요소를 사용하면 된다. "child: "의 경우 똑같이 Widget 1개를 구현하면되고 "children: "의 경우 children: <Widget>[AWidget(), BWidget(), ...] 처럼 여러개의 Widget을 구현하면 된다. (**여러개의 Widget을 구현하고 싶을 때 요소에 child만 있고 children이 없는 경우 child에 구현하는 Widget을 children 요소가 있는 Widget으로 할당하면 된다. 대표적으로 예제에 Column이 있다.)

return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );

- Center

 Center는 눈에 보이는 Widget은 아니고 child에 할당되는 Widget을 중앙에 배치해주는 Widget이다.

- Column, Row

 Column역시 눈에 보이는 Widget은 아니다. children에 여러개의 Widget을 할당하고 할당된 각 Widget을 열에 따라 정렬해준다. 비슷한 Widget으로 Row가 있으며 Row는 할당된 각 Widget을 행에 따라 정렬해준다. (Expanded Widget과 함께 사용하면 유용하다. 자세한건 https://cdl-dev.tistory.com/12 참조)

 

Flutter TabBar

전체코드 import 'package:flutter/material.dart'; import 'package:flutter_swiper/flutter_swiper.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { // This widget is the roo..

cdl-dev.tistory.com

- floatingActionButton

 floatingActionButton은 onPressed: 요소에 Button을 클릭했을 때 동작하는 함수를 할당하여 동작시킨다. 예제에서는 _incrementCounter() 함수를 할당하여 setState() 함수를 호출한다.

int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

- setState

 setState()함수는 StatefulWidget에 기본적으로 구현되어있는 함수로 변화를 감지하여 Widget을 출력 하는 역할을 한다. 예제에서는 _counter를 증가시킨 후 Widget을 출력하여 $_counter가 포함된 Text가 _counter에 맞게 변화한다. (**Text에 변수값을 넣고 싶다면 예제와 같이 변수명 앞에 $를 붙이면 된다.)

(cmd + B) (왼쪽) Center / (중앙) Column / (오른쪽) Text 의 요소들

 

실행결과는 다음과 같다

 

Tip 요약

**cmd + B (Window는 Ctrl + B) : 정의로 이동, 구현으로 이동

** _ : private

** StatefulWidget : createState 반드시 Override

** $ : 문자데이터에 변수값 할당해주는 연산자

'Flutter' 카테고리의 다른 글

Flutter Swiper  (0) 2020.07.21
Flutter 기본 Widget 구현  (0) 2020.07.17
Flutter + ARFoundation 기본세팅 (Windows)  (0) 2020.06.19
Flutter + Unity(IOS)  (0) 2020.06.19
Flutter 설치 (MAC)  (0) 2020.06.18