[flutter] 기본 개념

Shin·2022년 11월 14일
0

flutter

목록 보기
1/6
post-custom-banner

플러터 설계 컨셉

1. Widget : 모든 것은 위젯이다

플러터에서 가장 중요한 개념은 위젯이라는 개념이다
플러터에서 화면 안의 모든 요소들은 위젯이 된다
플러터의 화면 구조는 여러 위젯들이 트리 형태로 구성되어 있다

class MyWidget extends Widget{
	String title; // 프로퍼티(멤버)
    String description;
    int count'
    Widget child; // 자식 위젯
    
    MyWidget({this.title, this.description, this.count}); // 생성자
    
    @override
    Widget build(BuildContext context){
    	return ...;
    }
}

2. State: 반응성(Reactive) 구현

상태(State)는 말 그대로 어떤 상태에 대한 값을 저장하는 변수를 가리킨다
상태는 어떤 이벤트가 발생한다면 다른 상태로 바뀌게 된다
상태는 정말 다양한 방법으로 사용되는데, 로그인 여부나 찜하기 등 정말 다양한 상태가 사용된다

3. Stream : 필요한 데이터가 있으면 찾아간다

스트림(Stream)은 흐름이라는 뜻으로, 시간이 지남에 따라 발생하는 데이터의 흐름이라고 이해할 수 있다
데이터를 불러오는 데 시간이 오래 걸리거나, 지속적으로 데이터를 받아야 하는 경우 스트림을 통해 구현하게 된다
스트림을 통해 받는 데이터들은 언제 수신이 완료되는 지 명확히 알 수 없다는 단점이 있기 때문에 데이터를 생산하는 영역과 사용하는 영역을 구분해 구현되며, 말 그대로 '구독'해 변화를 확인할 수 있다


플러터의 기본 위젯

Container : 가장 기초가 되는 위젯

Container 위젯은 큰 상자처럼 위젯을 담는 역할을 하며 Padding(여백)을 설정할 수 있다

Container의 옵션

  • EdgeInsets : 여백을 주기 위해 위젯을 사용하며 [all, frorLTRB, only, symmetric] 방식이 있다
  • color : 상자의 배경색을 설정한다
  • width, height : 너비와 높이를 설정한다
Container(
	child: Text('Hello, Flutter!'),
    padding: EdgeInsets.all(30),
    color: Colors.blue,
    height: 300,
    width: 300,
)

image : 이미지 넣기

image는 이미지를 넣기 위한 위젯이다
로컬에 저장한 이미지를 사용하기 위해선 pubspec.yaml 파일에 이미지를 등록해야 한다
또한 크기 지정 시 설정 크기와 원본의 비율이 다를 경우 원본을 지키는 쪽으로 설정된다

assets:
  - images/flutter_logo.png  #예시

image의 옵션

  • Image.asset : 로컬 내에 있는 이미지를 불러오는 방법
  • Image.network : 인터넷의 이미지를 불러오는 방법
  • width, height : 너비와 높이를 설정한다
Image.asset('images/flutter_logo.png')
Image.network('https://~')

Text: 텍스트 위젯

문자열을 나타낼 수 있는 위젯으로, child를 사용하지 않고 문자열을 집어넣으면 화면이 출력된다
TextStyle 위젯을 통해 문자열을 꾸밀 수 있다

TextStyle의 옵션

  • fontSize, color, fontweight 등
Text(
	'Hello, Text Widget!',
    style: TextStyle(
    	fontSize: 25,
        color: Colors.purple,
        fontFamily: '지정',
        fontWeight: FontWeight.w700,
    ),
)

Column, Row

화면에 위젯을 배치할 때 도움을 주는 위젯으로, 플러터에는 대표적으로 Column, Row, ListView, Stack가 있다
Column은 위에서 아래로, Row는 좌에서 우로 위젯들을 배치한다
여러 위젯들을 감싸기 때문에 children을 사용한다

Column, Row의 옵션

  • mainAxisAlignment : 위에서 아래로 가는 방향에서 어떤 기준을 정렬할 지 결정 (Row는 반대)
    center, start, end, spaceEvenly, spaceAround, spaceBetween 등
  • crossAxisAlignment : 왼쪽에서 오른쪽을 가는 방향에서 어떤 기준으로 정렬할 지 결정
    center, start, end 등

ListView : 스크롤 할 수 있는 화면 만들기

Column이나 Row는 화면을 벗어날 만큼 많은 양의 데이터가 있으면 Buttom Overflowed가 발생한다
ListView는 많은 양의 데이터가 들어와도 스크롤이 가능한 화면을 구성하게 해준다

ListView의 옵션

  • scrollDirection : 스크롤 방향을 지정해 좌우 방향으로도 사용이 가능하다
    Axis.horizontal

ListView는 builder라는 함수를 활용해 만드는 방법도 존재한다
ListView.builder(
	itemCount: 50,
    itemBuilder: (BuildContext context, int index) {
    	return Text(
        	'$index' + ' Text',
            style: TextStyle(fontSize: 25),
        );
	}
),

Stack : 위젯 위에 위젯 쌓기

Stack 위젯은 위젯 위에 위젯을 쌓고 싶을 때 사용한다
좀 더 정밀하게 만들기 위해 위치를 지정할 수 있는 Positioned라는 위젯의 도움을 받기도 한다

Stack(
   children: [
    Image.asset('images/flutter_logo.png'),
    Positioned(
      left: 0,
      bottom: 0,
      child: Image.network(
        'https://~',
        width: 100,
        height: 100,
      ),
    ),
  ],
),

Positioned 위젯으로 감싸고 leftd와 bottom값을 0으로 설정했는데, 이는 좌측 방향으로 0만큼, 하단 방향으로 0만큼 떨어지게끔 배치하라는 설정이다

Button : TextButton, ElevatedButton, OutlinedButton

플러터에는 위 버튼에 IconButton까지 총 4종류의 버튼이 존재한다

Center(
  child: Column(
   mainAxisAlignment: MainAxisAlignment.center,
   children: [
   	 // Text 위젯만 존재
     TextButton(onPressed: (){}, child: Text('Text Button'),),
     Padding(padding: EdgeInsets.all(20)),
     // 배경색이 칠해져 있는 상태의 버튼
     ElevatedButton(onPressed: (){}, child: Text('Elevated Button'),),
     Padding(padding: EdgeInsets.all(20)),
     // 테두리가 그려져 있는 버튼
     OutlinedButton(onPressed: (){}, child: Text('Outlined Button'),),
     Padding(padding: EdgeInsets.all(20)),
     // icon()을 인자로 받아 아이콘 형태의 버튼
     IconButton(onPressed: (){}, icon: Icon(Icons.star),),
     Padding(padding: EdgeInsets.all(20)),
   ],
  ),
 ),

우선 공통적으로 버튼들은 onPressed라는 프로퍼티를 가지고 있다
여기에는 함수가 인자로 들어가며, 버튼을 눌렸을 때 어떤 일을 수행할지 정의하면 된다


위 위젯 이외에도 많은 위젯들이 존재한다 또한 누구나 만들 수 있고, 배포할 수 있다 [pub.dev](https://pub.dev/)

화면 전환 구현하기

화면 전환은 가장 기본적인 이벤트 중 하나다
대부분의 앱은 화면이 여러개이고, 버튼 등을 눌러 해당 화면으로 이동하게 된다

화면 이동(Navigator.push)

모든 화면 전환 관련 이벤트는 Navigator라는 위젯을 통해 처리된다
Navigator를 활용하면 화면을 특정 화면으로 이동하거나, 이전 화면으로 돌아가는 기능을 구현할 수 있다

ElevatedButton(
	onPressed: () {
		Navigator.of(context).push(
			MaterialPageRoute(
				builder: (BuildContext context) => SecondScreen(),
			),
		);
	},
	child: Text('Go to Second Screen'),
),

Navigator.of(context)로 시작하는데, 이는 현재 위젯인 Scaffold 화면에서 이동하겠다는 뜻이다
여기에 Push로 화면을 쌓아 이동을 구현한다
또한 MaterialPageRoute를 통해 Navigator가 이동할 경로를 지정해준다

화면 뒤로 가기(Navigator.pop)

ElevatedButton(
	onPressed: () {
		Navigator.of(context).pop();
	},
	child: Text('Go to Second Screen'),
),

Navigator.of(context)까지는 동일하지만, .pop()으로만 끝난다

화면 이동할 때 데이터 전달하기

화면 클래스의 생성자를 활용해서 객체를 생성할 때 객체 내의 변수에 해당 인자 값을 저장할 수 있다
이를 활용해 화면을 이동할 때 데이터를 넘겨주는 기능을 구현할 수 있다

클래스 인자 전달

ElevatedButton(
	onPressed: () {
		Navigator.of(context).push(
			MaterialPageRoute(
				builder: (BuildContext context) => SecondScreen(
                	screenData: 'Data from FirstScreen',
                ),
			),
		);
	},
	child: Text('Go to Second Screen'),
),

클래스 인자 사용

final String ScreenData;
SecondScreen({required this.screenData});

// (생략)...

ElevatedButton(
	onPressed: () {
		Navigator.of(context).pop();
	},
	child: Text('screenData : ' + screenData),
),

Stateless & Stateful

StatelessWidget은 위에서 계속 사용했던 위젯으로, 상태가 없는 위젯이다
제목이나 이미지와 같이 변하지 않는 위젯들은 StatelessWidget로 구현할 수 있다

StatefulWidget은 상태를 포함한 위젯이다
상태를 선언할 수 있고, 변화가 감지되었을 때 변화에 대한 이벤트를 수행한다

import 'package:flutter/material.dart';

class FirstScreen extends StatefulWidget {

  
  State<FirstScreen> createState() => _FirstScreenState(); // 1번
}

class _FirstScreenState extends State<FirstScreen> { // 2번
  
  
  void initState() { // 3번
    // TODO: implement initState
    super.initState();
  }
  
  
  Widget build(BuildContext context) { // 4번
    return Scaffold(
      appBar: AppBar(),
      body: Center(),
    );
  }
  
  
  void dispose() { // 5번
    // TODO: implement dispose
    super.dispose();
  }
}
  1. createState()라는 메소드를 사용하여 Statef를 생성한다
    StatefulWidget은 그 내부에서 사용할 State를 생성하는 것으로 그 역할을 다한다
  2. State 또한 플러터 내부에서 선언된 클래스인데, 이를 상속받아_FirstScreenState라는 클래스를 만들었다
    앞에 _를 붙이는 것은 관례적인 표현이다
  3. 앞서 생성한 State를 초기화하는 단계로, 필수적이진 않다
    super.initState()를 통해 부모 클래스의 initState() 메소드를 함께 실행한다
  4. StatelessWidget과 동일하다
  5. dispose()는 위젯이 사라질 때 실행되는 단계로, 역시 필수적이진 않다

출처 : 쉽고 빠른 플러터 앱 개발

post-custom-banner

0개의 댓글