본문 바로가기
개발 공부/Flutter

[Flutter/기본] Flutter - 위젯, 레이아웃

by 깐테 2021. 12. 22.
  • flutter dart 파일은 lib 내부에 위치. 이를 벗어나면 실행되거나 적용되지 않음.
  • ios, android는 네이티브로 동작하기 위한 파일들

 

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(
      // Application name
      title: 'Flutter Stateful Clicker Counter',
      theme: ThemeData(
        // Application theme data, you can set the colors for the application as
        // you want
        primarySwatch: Colors.blue, // 앱의 메인 컬러 변경.
      ),
      home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {// 상태가 바뀜.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    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(
          mainAxisAlignment: MainAxisAlignment.center, // 컬럼을 중앙에 놓는다.
          children: <Widget>[ // 컬럼은 여러개의 줄을 넣기 때문에 children을 사용.
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter', // $로 표시하면 int로 선언된 카운터가 0으로 자동으로 시작.
              style: TextStyle(fontSize: 25),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter, // 눌렀을때, _incrementCounter 함수 호출.
        tooltip: 'Increment',
        child: Icon(Icons.add), 
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

 

  • 코드는 무조건 main함수부터 시작.
  • 눈에 보이지 않는 요소도 위젯이지만, Stateless는 상태변화가 없는 요소.
  • pubspec.yaml에 버전이 2.12 이상이어야 null safety 적용.
  • Stateful 위젯은 따로 호출되는 것이 있다.
  • Stateful 위젯에서 제일 핵심은setState(). 상태를 변경시킨다.
  • Column은 여러개의 줄을 넣기 때문에 children을 사용.
  • $로 표시하면 int로 선언된 카운터가 0으로 자동으로 시작.
  • 위젯 안에 위젯을 넣기 위해서는 child, children. 여러개 들어가야 되는 경우면 children, 하나면 child.
  • setState 안에 상태변화와 관련된 코드를 넣어야 동작 시 상태변화를 일으킨다.

 

Container

 

  • 아무것도 없는 위젯.
  • 컨테이너는 기본적으로 자식 위젯을 하나밖에 가지지 못한다. 그럴 떄에는 Column을 사용하면 여러개의 자식 위젯을 가질 수 있다.
  • Row를 이용하면 여러개의 내용을 수평으로 배치할 수 있다. ex) 아이콘 → 내용.
  • 플러터에서 줄간격, 열간격을 조정하는 방법은 다양하다.
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(
      // Application name
      title: 'Flutter Stateful Clicker Counter',
      theme: ThemeData(
        // Application theme data, you can set the colors for the application as
        // you want
        primarySwatch: Colors.blue, // 주요 색상 변경
      ),
      home: MyHomePage(title: 'Flutter Demo Clicker Counter Home Page'),
    );
  }
}

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

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        //color: Colors.blue,
        children: <Widget>[
          Text('Hello World!'),
          Text('Hello World!'),
        ],
      ),
    );
  }
}
body: Column(
        //color: Colors.blue,
        children: <Widget>[
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              Icon(Icons.add),
              Column(
                children: <Widget>[
                  Text('title'),
                  Text('SubTitle'),
                ],
              ),
              Icon(Icons.arrow_forward),
            ],
          ),
          Divider(),
        ],
      ),
  • Stack은 배경 이미지를 구성할 때 주로 사용된다.

 

SingleChildScrollView

 

  • 화면을 구성하다 보면 화면의 크기를 넘어서 스크롤이 필요한 경우가 있다.
  • SingleChildScrollView은 하나의 자식을 포함하는 스크롤이 가능한 위젯이다.

 

 

SingleChildScrollView VS ListBody

 

  • SingleChildScrollView는 Column을 사용한다.
  • Column 은 기본적으로 표시할 위젯의 크기만큼 가로 길이를 가진다. 따라서 스크롤 가능 영역이 좁을 수 있다.
  • 반면 ListBody를 사용하면 스크롤 가능한 영역이 가로로 꽉차서 사용자가 스크롤하기 더 쉽다.

 

 

Listview, ListTile

 

  • ListView는 리스트를 표시하는 위젯이다.
  • ListTile은 하나의 리스트가 되는 위젯이다.
  • 즉, ListView가 하나의 서랍이라 한다면, ListTile은 서랍에 들어가는 서랍장이라고 할 수 있다.

 

body: ListView(
        scrollDirection: Axis.vertical,
        children: [ // 다수의 위젯을 배치 할 수 있는 children
          ListTile(
            leading: Icon(Icons.home),// title특성의 앞 부분을 꾸미는 특성
            title: Text("홈"), // 제목을 붙일 수 있는 특성
            trailing: Icon(Icons.navigate_next),//title특성의 뒤를 꾸미는 특성
            onTap: (){},
          ),
          ListTile(
            leading: Icon(Icons.event),
            title: Text("학사일정"),
            trailing: Icon(Icons.navigate_next),
            onTap: (){},
          ),
          ListTile(
            leading: Icon(Icons.qr_code),
            title: Text("Qr인증"),
            trailing: Icon(Icons.navigate_next),
            onTap: (){}, // 눌렀을 때, 화면 구성.
          ),
        ],
      )
    );
  }
}

 

GridView

  • 열 수를 지정하여 그리드 형태로 표시하는 위젯
  • 특징은 count를 사용하여 표시할 열 수를 조정.
  • Adobe XD, Figma 등을 이용하면 해당 사이트에서 디자인을 만들어 두면 플러터에서 컨버팅 가능.
body: GridView.count(crossAxisCount: 3, // 열 수
      children: [
        Container(
          color: Colors.amber,
          width: 100,
          height: 100,
          padding: const EdgeInsets.all(8.0),//안쪽 여백
          margin: const EdgeInsets.all(8.0),// 바깥쪽 여백
        ),
        Container(
          color: Colors.blue,
          width: 100,
          height: 100,
          padding: const EdgeInsets.all(8.0),
          margin: const EdgeInsets.all(8.0),
        ),
        Container(
          color: Colors.greenAccent,
          width: 100,
          height: 100,
          padding: const EdgeInsets.all(8.0),
          margin: const EdgeInsets.all(8.0),
        ),
        ...
				...
      ],)

 

PageView

  • 여러 페이지를 좌우로 슬라이드하여 넘길 수 있도록 해주는 위젯이다.
body:PageView(children: [
      Container(color: Colors.redAccent),
      Container(color: Colors.yellowAccent),
      Container(color: Colors.greenAccent),
      Container(color: Colors.blueAccent),
      ],)

 

AppBar

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text("Myongji College"),
          centerTitle: true, // 타이틀을 가운제로 정렬.
          backgroundColor: Colors.red[600],
          elevation: 0.0,
          leading: Icon(Icons.arrow_back),// 왼쪽
          actions: [Icon(Icons.search), Icon(null)],
					// 오른쪽에 공간을 만들어 주기 위해 NULL아이콘 하나 배치.
					// padding을 넣어주어도 가능. 디자이너 자유.
        ),
        body: Container());
  }
}

 

Drawer

  • body와 같은 레벨에 위치한다(하위가 아님).
  • Drawer를 만들면 관련 리스트 뷰를 자동으로 추가해준다.

 

  • 참고 사이트

https://flutter.dev/docs/development/ui/layout

 

Layouts in Flutter

Learn how Flutter's layout mechanism works and how to build a layout.

docs.flutter.dev

Dart packages

 

Dart packages

Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter, AngularDart, and general Dart programs.

pub.dev

Dart packages

 

Dart packages

Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter, AngularDart, and general Dart programs.

pub.dev

 

반응형