๊ณต๋ถ€/flutter

[Flutter] Flutter ์‹œ์ž‘

whaeun 2022. 1. 23. 23:56

๐Ÿ–ฅ Flutter

๐ŸŒŸ Flutter ๊ฐ•์˜

  1. ํ”Œ๋Ÿฌํ„ฐ ์‹œ์ž‘
  2. ํ”Œ๋Ÿฌํ„ฐ ์„ค์น˜
  3. ์นด์šดํŒ… ์•ฑ ๋งŒ๋“ค๊ธฐ
  4. ๋ ˆ์ด์•„์›ƒ ํŠœํ† ๋ฆฌ์–ผ



๐Ÿ‘ฉ๐Ÿฝ‍๐Ÿ’ป ๊ฐ•์˜ ๋‚ด์šฉ ์ •๋ฆฌ

  1. ํ”Œ๋Ÿฌํ„ฐ(Flutter)๋ž€?
  • "dart"๋ผ๋Š” ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋ฐ”์ผ์šฉ ๊ฐœ๋ฐœ ํ”Œ๋žซํผ์ด๋‹ค.
  • IOS์™€ Android๋ฅผ ๋ชจ๋‘ ํ•œ๋ฒˆ์— ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋Š” ํด๋กœ์Šค ํ”Œ๋žซํผ์„ ์ง€์›ํ•œ๋‹ค.
  • dart๋ผ๋Š” ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ ๋„ค์ดํ‹ฐ๋ธŒ ์„ฑ๋Šฅ์„ ๋‚ผ ์ˆ˜ ์žˆ๋‹ค. (๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•ด ์†๋„๊ฐ€ ๋น ๋ฅด๋‹ค.)
  • * flutter ์‚ฌ์ดํŠธ: https://flutter.dev

    * Cross Platform์ด๋ž€ ์—ฌ๋Ÿฌ ์ข…๋ฅ˜์˜ ์ปดํ“จํ„ฐ ํ”Œ๋žซํผ์—์„œ ๋™์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ๋œปํ•˜๋Š” ์šฉ์–ด์ด๋‹ค. (= ๋ฉ€ํ‹ฐํ”Œ๋žซํผ ์†Œํ”„ํŠธ์›จ์–ด)
    image



  1. ์นด์šดํŒ… ์•ฑ ๋งŒ๋“ค๋ฉฐ ๊ธฐ๋ณธ ๊ตฌ์กฐ ํŒŒ์•…ํ•˜๊ธฐ
    import 'package:flutter/material.dart';
    void main() => runApp(MyApp());
    // st => stateless๋ฅผ ์„ ํƒํ•˜๋ฉด stateless ์ฝ”๋“œ๊ฐ€ ์ƒ์„ฑ๋จ.
    // StatelessWidget์€ ๋ฐ”๋€Œ์ง€ ์•Š๋Š” ์ •์ ์ธ ๊ฒƒ์ด๋‹ค.
    class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
     return MaterialApp(
       title: 'Flutter Demo',
       theme: ThemeData(primarySwatch: Colors.blue),
       home: MyHomePage(title: 'Flutter Demo Home Page'),
     );
    }
    }
    //option + enter๋ฅผ ํ†ตํ•ด class ์ƒ์„ฑ ๊ฐ€๋Šฅ
    // StatefulWidget์€ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค.
    class MyHomePage extends StatefulWidget {
    //๊ฐ•์˜ ์˜์ƒ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ KEY key๋ผ ์“ฐ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋‚จ. - Key can't have a value of "null" (๐Ÿ’ฅ trouble shooting)
    MyHomePage({Key? key, required this.title}) : super(key: key);
    final String title;
    @override
    _MyHomePageState createState() => _MyHomePageState();
    }
    class _MyHomePageState extends State<MyHomePage> {
    // _๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๊ฒƒ์€ private๋ฅผ ์˜๋ฏธํ•จ. - ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋“ค (๋ณด์•ˆ์ ์ธ ์š”์†Œ)
    int _counter = 0;
    @override
    Widget build(BuildContext context) {
     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),
       ),
     );
    }
    void _incrementCounter() {
     setState((){
       _counter++;
     });
    }
    }

2.1. stateless์™€ stateful์˜ ์ฐจ์ด

  • stateless : ์ด์ „ ์ƒํƒœ๋ฅผ ๊ธฐ๋กํ•˜์ง€ ์•Š์•„ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋‹ค ์ ‘์†์ด ๋Š์–ด์งˆ ๊ฒฝ์šฐ, ์ž‘์—…์„ ์ƒˆ๋กœ์ด ์‹œ์ž‘ํ•ด์•ผ ํ•œ๋‹ค.
  • stateful : ์‚ฌ์šฉ์ž์˜ ์š”์ฒญ์„ ์„œ๋ฒ„๊ฐ€ ๊ธฐ๋กํ•˜๊ณ  ์žˆ์–ด ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋‹ค ์ ‘์†์ด ๋Š์–ด์ง€๋”๋ผ๋„ ์ด์ „์— ๊ธฐ๋ก๋œ ๋‹จ๊ณ„์—์„œ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋ฉด ๋œ๋‹ค.

2.2. flutter ์ •๋ ฌํ•˜๊ธฐ - MainAxisAlignment, CrossAxisAlignment

  • mainaxis๋Š” ์ฃผ์ถ•, crossaxis๋Š” ํšก์ถ•์„ ์˜๋ฏธํ•œ๋‹ค.
  • ํ–‰์˜ ๊ฒฝ์šฐ main axis๋Š” ๊ฐ€๋กœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•˜๊ณ  cross axis๋Š” ์„ธ๋กœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•œ๋‹ค.
  • ์—ด์˜ ๊ฒฝ์šฐ main axis๋Š” ์„ธ๋กœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•˜๊ณ  cross axis๋Š” ๊ฐ€๋กœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•œ๋‹ค.

    image

2.3. MainAxisAlignment์™€ CrossAxisAlignment ์˜ˆ์‹œ

- MainAxisAlignment

1) MainAxisAlignment.center: row์ผ ๊ฒฝ์šฐ, ๊ฐ€๋ก์ถ• ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์„ธ๋กœ์ถ• ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ
2) MainAxisAlignment.start: row์ผ ๊ฒฝ์šฐ, ๊ฐ€๋ก์ถ• ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์„ธ๋กœ์ถ• ๊ธฐ์ค€์œผ๋กœ ์œ„์ชฝ์œผ๋กœ ์ •๋ ฌ
3) MainAxisAlignment.end: row์ผ ๊ฒฝ์šฐ, ๊ฐ€๋ก์ถ• ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์„ธ๋กœ์ถ• ๊ธฐ์ค€์œผ๋กœ ์•„๋ž˜์ชฝ์œผ๋กœ ์ •๋ ฌ
4) MainAxisAlignment.spaceEvently: child widget ์‚ฌ์ด์˜ ์—ฌ์œ  ๊ณต๊ฐ„์„ ๋ชจ๋‘ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ฐฐ๋ถ„
5) MainAxisAlignment.spaceBetween: child widget์„ ์‹œ์ž‘๊ณผ ๋์— ๋ฐฐ์น˜ํ•˜๊ณ  ์œ„์ ฏ ์‚ฌ์ด์˜ ์—ฌ์œ  ๊ณต๊ฐ„์„ ๋ชจ๋‘ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ฐฐ๋ถ„
6) MainAxisAlignment.spaceAround: ์ฒซ๋ฒˆ์งธ์™€ ๋งˆ์ง€๋ง‰ child ์•ž ๋’ค์˜ ์—ฌ์œ ๊ณต๊ฐ„์„ ๋‚˜๋จธ์ง€ child์™€ ๊ณต๊ฐ„์˜ ์ ˆ๋ฐ˜๋งŒํผ ๋ฐฐ์น˜

- CrossAxisAlignment

1) CrossAxisAlignment.center: row์ผ ๊ฒฝ์šฐ, ๊ฐ€๋ก์ถ• ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์„ธ๋กœ์ถ• ๊ธฐ์ค€์œผ๋กœ ๊ฐ€์šด๋ฐ ์ •๋ ฌ
2) CrossAxisAlignment.start: row์ผ ๊ฒฝ์šฐ, ๊ฐ€๋ก์ถ• ๊ธฐ์ค€์œผ๋กœ ์œ„์ชฝ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์„ธ๋กœ์ถ• ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ ์ •๋ ฌ
3) CrossAxisAlignment.end: row์ผ ๊ฒฝ์šฐ, ๊ฐ€๋ก์ถ• ๊ธฐ์ค€์œผ๋กœ ์•„๋ž˜๋กœ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์„ธ๋กœ์ถ• ๊ธฐ์ค€์œผ๋กœ ์˜ค๋ฅธ์ชฝ ์ •๋ ฌ
4) CrossAxisAlignment.stretch: ์ขŒ์šฐ๋ฅผ ๊ฝ‰์ฐจ๊ฒŒ ๋ฐฐ์น˜ 5) CrossAxisAlignment.baseline: row์ผ ๊ฒฝ์šฐ, ์ˆ˜ํ‰ ์ •๋ ฌ / column์˜ ๊ฒฝ์šฐ, ์ˆ˜์ง ์ •๋ ฌ

 

2.4. ๋ ˆ์ด์•„์›ƒ ๋ฐฐ์น˜์™€ ๋ฐ˜์‘ํ˜• ์•ฑ ์—ฐ์Šต

import 'package:flutter/material.dart';


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

//๐Ÿ’ฅ trouble shooting - type 'MyApp' is not a subtype of type 'StatelessWidget'"
// https://stackoverflow.com/questions/51334839/another-exception-was-thrown-type-myapp-is-not-a-subtype-of-type-statelesswi
// MyApp์„ ๋ณ€๊ฒฝํ•  ๊ฒฝ์šฐ restart ํ•ด์•ผ ํ•จ.

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}


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

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

class _MyHomePageState extends State<MyHomePage> {

  bool _isStared = true;
  int _count = 41;

  @override
  Widget build(BuildContext context) {
    //MainAxisAlignment์™€ CrossAxisAlignment๋กœ ์ •๋ ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
    var titleSection = Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text('Cat is so cute.',
                style: TextStyle(fontWeight: FontWeight.bold, fontSize: 26)),
            Text('This is layout practice.',
                style: TextStyle(color: Colors.grey, fontSize: 26)),
          ],
        ),
        //padding ์„ค์ •
        Padding(padding: EdgeInsets.all(10.0),),
        //Icon์˜ ํฌ๊ธฐ ์„ค์ • ๊ฐ€๋Šฅ
        //์‚ผํ•ญ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ Bool ? A : B
        IconButton(
          onPressed: _pressedStar,
          //icon button ์•ˆ์— icon์ด ๋“ค์–ด๊ฐ€๋Š” ํ˜•์‹
          icon: (_isStared ? Icon(Icons.star) : Icon(Icons.star_border)),
          color: Colors.deepOrange,),
        Text('$_count', style: TextStyle(fontSize: 30),)
      ],
    );

    var buttonSection = Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[

        Column(
          children: <Widget>[
            Icon(Icons.call, size: 30, color: Colors.lightBlue,),
            Text("CALL", style: TextStyle(color: Colors.lightBlue),)],
        ),

        Padding(padding: EdgeInsets.all(40.0),),

        Column(children: <Widget>[
          Icon(Icons.near_me, size: 30, color: Colors.lightBlue,),
          Text("ROUTE", style: TextStyle(color: Colors.lightBlue),)],
        ),

        Padding(padding: EdgeInsets.all(40.0),),

        Column(children: <Widget>[
          Icon(Icons.share, size: 30, color: Colors.lightBlue,),
          Text("SHARE", style: TextStyle(color: Colors.lightBlue),)],
        ),
      ],
    );

    // Container์— padding์„ ๋„ฃ์„ ๊ฒฝ์šฐ, ์œ„ ์•„๋ž˜ ์–‘ ์˜†์— ๋‹ค ๋“ค์–ด๊ฐ„๋‹ค.
    var textSection = Container(
      child: Text(
          "The cat (Felis catus) is a domestic species of a small carnivorous mammal."
              " It is the only domesticated species in the family Felidae and "
              "is often referred to as the domestic cat to distinguish it from the wild "
              "members of the family. A cat can either be a house cat, a farm cat or"
              " a feral cat; the latter ranges freely and avoids human contact."
              " Domestic cats are valued by humans for companionship and their ability to"
              " kill rodents. About 60 cat breeds are recognized by various cat registries.",
          style: TextStyle(fontSize: 15)),
      padding: EdgeInsets.all(20.0),
    );

    return Scaffold(
      body: Column(
        //์™ธ๋ถ€ ๋งํฌ๋กœ๋ถ€ํ„ฐ ์‚ฌ์ง„์„ ๋ฐ›์•„์™€์„œ ํ‘œ์‹œํ•˜๋Š” ๊ฒƒ์€ network๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค.
        children: <Widget>[
          Image.network("https://user-images.githubusercontent.com/61380136/150347579-6cd5462e-0a75-467a-a0f2-2dd9c16d3744.png",
            height: 240, width: 600, fit: BoxFit.cover,),
          Padding(padding: EdgeInsets.all(10.0),),
          titleSection,
          Padding(padding: EdgeInsets.all(1.0),),
          buttonSection,
          //Padding(padding: EdgeInsets.all(1.0),),
          textSection,
        ],
      ),
    );
  }

  void _pressedStar() {
    setState(() {
      if (_isStared){
        _isStared = false;
        _count -= 1;
    } else{
        _isStared = true;
        _count += 1;
      }
    });
  }
}

- ์‹คํ–‰ ํ™”๋ฉด

 

๐Ÿ’ฅ Trouble Shooting ๐Ÿ’ฅ

  1. Ctrl + Space ํ•ด๋„ ์–ด๋–ค ์†์„ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์•ˆ๋œจ๊ณ  Spot light๊ฐ€ ๋œจ๋Š” ๋ฌธ์ œ
    => ํ™˜๊ฒฝ ์„ค์ •์—์„œ ํ•ด๋‹น ๋‹จ์ถ•ํ‚ค๋ฅผ ๋ณ€๊ฒฝํ•œ๋‹ค.
  2. Key can't have a value of "null"
    => ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์›์ธ: null safety๊ฐ€ ํ™œ์„ฑํ™”๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. null์ด ๋  ์ˆ˜ ์—†๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋‚˜ ํ‚ค๊ฐ€ null ๊ฐ’์„ ๊ฐ€์ง€์ง€ ์•Š๋„๋ก ํ•œ๋‹ค.
    => ํ•ด๊ฒฐ๋ฐฉ๋ฒ•: null์ด ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ์„ ๋‚˜ํƒ€๋‚ด๋„๋ก ํ•˜๋Š” ?์™€ ๊ฐ’์ด ๊ผญ ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค๊ณ  ํ‘œ์‹œํ•ด์•ผ ํ•˜๋Š” required๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ error๋ฅผ ํ•ด๊ฒฐํ–ˆ๋‹ค.

    # ํ•ด๋‹น ์˜ค๋ฅ˜๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•
    1) required:  
    2) Default value: 
    3) Nullable parameter: 
    4) Positional parameters: 

๐Ÿ“ ์ฐธ๊ณ  ์ž๋ฃŒ