본문 바로가기

Flutter

Flutter 기본 Widget 구현

전체코드

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(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  final String title;

  @override
  WidgetSample createState() => WidgetSample();
}

class WidgetSample extends State<MyHomePage>{
  @override
  Widget build(BuildContext context){
    double appBarHeight = 50.0;
    return MaterialApp(
      home: Scaffold(
        appBar: PreferredSize(
          preferredSize: Size.fromHeight(appBarHeight),
          child:AppBar(
            title: Text('Widget Demo'),
            backgroundColor: Colors.cyan,
          ),
        ),
        body: Red(),//Blue(), Green() 으로 바꿀 수 있다.
      ),
    );
  }
}

// Card 위젯 구현
class Red extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      child: Card(color: Colors.red)
    );
  }
}

// Text 위젯 구현
class Green extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return new LayoutBuilder(builder: (context, constraint) {
      double min = (constraint.biggest.width < constraint.biggest.height)
          ? constraint.biggest.width : constraint.biggest.height;
      return Container(
        width: constraint.biggest.width,
        height: constraint.biggest.height,
        color: Colors.green,
        child: Center(
          child: Text('GREEN',
            style: TextStyle(fontSize: min / 4, color: Colors.white, decoration: TextDecoration.none, fontWeight: FontWeight.normal)
          )
        )
      );
    });
  }
}

// Icon 위젯 구현
class Blue extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return new LayoutBuilder(builder: (context, constraint) {
      double min = (constraint.biggest.width < constraint.biggest.height)
          ? constraint.biggest.width : constraint.biggest.height;
      return Container(
        width: constraint.biggest.width,
        height: constraint.biggest.height,
        color: Colors.blue,
        child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
      );
    });
  }
}

PrefferedSize

appBar에 바로 AppBar Widget을 할당하지 않고 PrefferedSize Widget을 할당하였다. PrefferedSize 는 appBar의 크기를 고정시킬 수 있는 역할을 한다. 지금은 size를 50으로 고정하였다.

Red, Green, Blue

class Red extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return Container(
      width: MediaQuery.of(context).size.width,
      height: MediaQuery.of(context).size.height,
      child: Card(color: Colors.red)
    );
  }
}

class Green extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return new LayoutBuilder(builder: (context, constraint) {
      double min = (constraint.biggest.width < constraint.biggest.height)
          ? constraint.biggest.width : constraint.biggest.height;
      return Container(
        width: constraint.biggest.width,
        height: constraint.biggest.height,
        color: Colors.green,
        child: Center(
          child: Text('GREEN',
            style: TextStyle(fontSize: min / 4, color: Colors.white, decoration: TextDecoration.none, fontWeight: FontWeight.normal)
          )
        )
      );
    });
  }
}

class Blue extends StatelessWidget {
  @override
  Widget build(BuildContext context){
    return new LayoutBuilder(builder: (context, constraint) {
      double min = (constraint.biggest.width < constraint.biggest.height)
          ? constraint.biggest.width : constraint.biggest.height;
      return Container(
        width: constraint.biggest.width,
        height: constraint.biggest.height,
        color: Colors.blue,
        child: Icon(Icons.access_alarms, size: min / 2, color: Colors.white),
      );
    });
  }
}

(왼쪽) Red, (중앙) Green, (오른쪽) Blue

 위 세개의 Widget은 기본적으로 동일하다. 요약하자면 Red는 Container Widget에 Card Widget으로 단순히 빨간화면을 출력하고, Green과 Blue는 Container Widget으로 각각 초록화면에 Text, 파란화면에 아이콘을 출력한다. 이전 글에서 Scaffold에 대해 간략하게 설명했었다. (https://cdl-dev.tistory.com/9) Scaffold가 전체 화면을 구성하는데 있어서 많이 쓰이는 기본 Widget이라면 Container는 Scaffold의 body요소에 거의 기본적으로 쓰이는 Widget이라 할 수 있다. 아마도 굉장히 많이 쓸 것이다.

- Container

 Widget을 담는 그릇이라고 생각하면 된다. width, height요소에 반드시 double형 변수를 할당해야 화면에 출력되며 Red의 경우 child 에 Card를 할당하여 모서리가 살짝 둥근 Widget을 출력하였다.

- MediaQuery.of(context).size, LayoutBuilder

 width, height요소에 Red는 MediaQuery.of(context).size가 할당되었고 Blue, Green은 constraint.biggest가 할당되었다. 두 경우 모두 Widget이 할당되는 공간에 대한 size 이지만 차이가 있다.

 MediaQuery의 경우 현재 Widget이 아닌 최상위 Widget의 전체 context에 대한 Data가 할당된다.(확실하진 않고 추측이다) 각 Widget은 당 한개의 context를 가지고 있고 Widget의 트리구조에따라 context도 트리구조를 갖는다. 아마도 context가 호출 될 때 최상위 루트의 context가 호출되는 듯 하다. 따라서 child를 통해 하위 Widget을 구현한다한들 최상위 Widget의 context가 전달되어 결국 고정된 값이 할당된다. (**context에 대한 설명은 https://paulaner80.tistory.com/entry/Widget-State-BuildContext-%EA%B7%B8%EB%A6%AC%EA%B3%A0-InheritedWidget 참조)

 constraint의 경우 현재 Widget에 대한 Data가 할당된다. constraint는 LayoutBuilder(builder: (context, constraint)...) 에 할당된 것으로 Widget의 Size에 따라 하위 Widget들의 Size 조절이 필요할 때 유용하다. constraint.biggest 는 LayoutBuilder가 사용할 수 있는 최대 Size를 제공한다. 아래의 경우 LayoutBuilder 는 Container 하위의 Center 하위에 있기 때문에 Container의 size인 (200, 200) 을 제공한다. (오차가 있을 수 있지만 거의 비슷함)

MediaQuery를 사용하면 Text 크기가 원하는 만큼 조절되지 않는다.
LayoutBuilder의 constraint를 사용하면 Text가 원하는 크기로 조절된다.

'Flutter' 카테고리의 다른 글

Flutter TabBar  (0) 2020.07.21
Flutter Swiper  (0) 2020.07.21
Flutter 기본예제  (0) 2020.07.15
Flutter + ARFoundation 기본세팅 (Windows)  (0) 2020.06.19
Flutter + Unity(IOS)  (0) 2020.06.19