반응형
반응형
반응형

위젯의 생명주기

 - 위젯이 화면에 그려지는 순간부터 삭제되는 순간까지의 주기를 의미

 - UI 를 표현할때 사용되는 대표적인 StatelessWidget 과 StatefulWidget 의 생명주기

 

StatelessWidget

 - 이름에서 알 수 있듯이 "상태가 없는 위젯"

 - StatelessWidget 이 빌드되면 생성자가 실행된다. 이어서 필수로 override 해야하는 build() 함수가 실행된다. build() 함수에 반환된 위젯이 화면에 렌더링된다.

 - 플러터에서 모든 위젯은 Widget 클래스를 상속 받는다. Widget 클래스는 불면(immutable) 특성을 갖고 있다. 클래스를 한번 생성하면 속성을 변경할 수 없다는 뜻이다.

 - 위젯의 속성을 변경해야 할 때가 있다. 예를 들어 생성자에 새로운 매개변수가 입력되는 경우. build() 함수에서 매개변수 값을 사용하고 있다면 변경된 매개변수 기반으로 build() 함수를 재실행해야 한다

 - StatelessWidget 은 불변이기 때문에 한 번 생성된 인스턴스의 build() 함수는 재실행되지 않는다. 화면에 변경된 내용을 반영하고 싶다면 새로운 인스턴스를 생성한 후 기존 인스턴스를 대체해야 한다.

 

StatefulWidget

 - StatefulWidget 은 StatelessWidget 과 다른 목적을 가지고 있다. 위젯 내부에서 build() 함수를 재실행해야 하는 상황에서 사용하는 위젯이다.

 - StatefulWidget은 Widget 클래스와 State 클래스 2개로 구성되어 있다. 

 - 상태 변경이 없는 생명주기

  √ 상태 변경이 없는 생명주기는 위젯이 화면에 나타나며 생성되고 화면에서 사라지며 삭제되는 과정을 의미한다.

   중간에 위젯의 상태가 변경되지 않는다.

      1. StatefulWidget 생성자 실행

      2. createState() 함수 실행. createState() 함수는 필수로 override 해야 하는 함수로 StatefulWidget 과 연동되는 State 를 생성한다.

      3. State 가 생성이되면 initState() 가 실행된다. initState() 는 State가 생성되는 순간 단 한번 실행되고 다시 실행되지 않는다.

      4. didChangeDependencies() 함수 실행. initState() 와 다르게 BuildContext 가 제공되고 State 가 의존하는 값이 변경되면 재실행된다.

      5. State 의 상태가 dirty 상태가 된다. dirty 상태는 build() 가 재실행되어야 하는 상태이다.

      6. build() 함수가 실행되고 UI 가 반영된다.

      7. build() 함수 실행이 완료되면 상태가 clean 상태로 변경된다. 화면에 변화가 없으면 이 상태가 유지된다.

      8. 위젯이 위젯 트리에서 사라지면 deactivate() 가 실행된다. deactivate() 는 State 가 일시적/영구적으로 삭제될때 실행된다.

      9. dispose() 가 실행된다. 위젯이 영구적으로 삭제될때 실행한다.

 

 

 - StatefulWidget 생성자의 매개변수가 변경됐을 때 생명주기

  StatefulWidgetStatelessWidget 처럼 하나의 클래스이다. 따라서 매개변수를 입력 받을 수 있다.

   위젯이 삭제되기 전에 매개변수가 변경된다면....

      1. StatefulWidget 생성자 실행

      2. State 의 didUpdateWidget() 함수 실행

      3. State 의 상태가 dirty 로 변경

      4. build() 함수 실행

      5. State 의 상태가 clean 으로 변경

 

 

 - State 자체적으로 build() 를 재실행할 때 생명주기

   StatelessWidget 은 생성될 때 build() 함수가 한번 실행되고 절대로 다시 실행되지 않는다.

  √ StatefulWidgetStatefulWidget 과 State 클래스로 구성되어 있는데, State 클래스는 setState() 함수를 실행해서 build() 함수를 재실행 할 수 있다.

      1. State 클래스의 setState() 함수 실행

      2. State 의 상태가 dirty 로 변경

      3. build() 함수 실행

      4. State 의 상태가 clean 으로 변경

 

 

이상 StatelessWidget 과 StatefulWidget 의 생명주기에 대해서 알아봤다.

앞으로 두 위젯을 써서 앱을 만들어보면서 더 익혀보기로 하자!!

반응형
반응형

1. 텍스트 관련 위젯

 - 화면에 글자를 보여주려면 글자를 렌더링할 수 있는 위젯을 사용.

Text(
	'텍스트 내용',
    style: TextStyle(
    	fontSize: 16.0,
        fontWeight: FontWeight.w700,
        color: Colors.blue,
    ),
)

 

2. 제스처 관련 위젯

 - 키보드로 글자를 입력하는 행위 외의 모든 입력을 제스처라고 한다.

 - 탭, 더블 탭, 길게 누르기, 드래그 등 모두가 제스처

 - 제스처 관련 위젯은 하위 위젯에 제스처가 입력됐을 때 인지하고 콜백 함수를 실행한다.

 

2-1. Button 위젯

▶ 텍스트만 있는 버튼

TextButton(
	onPressed: (){},
    style: TextButton.styleFrom(
    	foregroundColor: Colors.red,
    ),
    chlid: Text('텍스트 버튼'),
)

 

▶ 테두리가 있는 버튼

OutlinedButton(
	onPressed: (){},
    style: OutlinedButton.styleFrom(
    	foregroundColor: Colors.red,
    ),
    child: Text('테두리가 있는 버튼'),
)

 

▶ 입체적으로 튀어나온 느낌의 배경이 들어간 버튼

ElevatedButton(
	onPressed: (){},
    style: ElevatedButton.styleFrom(
    	backgroundColor: Colors.red,
    ),
    child: Text('입체적인 버튼'),
)

 

2-2. IconButton 위젯

 - 아이콘을 버튼으로 생성하는 위젯

 - onPressed 변수에 아이콘을 누르면 실행 할 콜백 함수 제공

IconButton(
	onPressed: (){},
    icon: Icon(
    	Icons.home,
    ),
)

 

2-3. GestureDetector 위젯

 - 앱은 모든 입력을 손가락으로 한다.

 - 손가락으로 하는 여러가지 입력을 인지하는 위젯

GestureDetector(
	onTap: (){
    	print('한 번 탭하기.');
    },
    onDoubleTap: () {
    	print('더블 탭하기.');
    },
    onLongPress: () {
    	print('길게 탭하기.');
    },
    onPanStart() {
    	print('수평 또는 수직으로 드래그가 시작됨.');
    },
    onPanUpdate() {
    	print('수평 또는 수직으로 드래그하는 동안 위치가 업데이트 될때마다 실행.');
    },
    onPanEnd() {
    	print('수평 또는 수직으로 드래그가 끝났을 때.');
    },
    onHorizontalDragStart() {
    	print('수평으로 드래그가 시작됨.');
    },
    onHorizontalDragUpdate() {
    	print('수평으로 드래그하는 동안 위치가 업데이트 될때마다 실행.');
    },
    onHorizontalDragEnd() {
    	print('수평으로 드래그가 끝났을 때.');
    },
    onVerticalDragStart() {
    	print('수직으로 드래그가 시작됨.');
    },
    onVerticalDragUpdate() {
    	print('수직으로 드래그하는 동안 위치가 업데이트 될때마다 실행.');
    },
    onVerticalDragEnd() {
    	print('수직으로 드래그가 끝났을 때.');
    },
    onScaleStart() {
    	print('확대가 시작됨.');
    },
    onScaleUpdate() {
    	print('확대가 진행되는 동안 위치가 업데이트 될때마다 실행.');
    },
    onScaleEnd() {
    	print('확대가 끝났을 때.');
    },
    child: Container(
    	decoration: BoxDecoration(
        	Color: Colors.red,
        ),
        width: 100.0,
        height: 100.0,
    ),
)

 

2-4. FloatingActionButton 위젯

 - 화면의 오른쪽 아래에 동그란 플로팅 작업 버튼 구현.

import 'package:flutter/material.dart'

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

class FloatingActionButtonExample extends StatelessWidget {
	@override
    Widget build(BuildContext context) {
    	return MateralApp(
        	home: Scaffold(
            	floatingActionButton: FloatingActionButton(
                	onPressed: (){},
                    child: Text('클릭'),
                ),
                body: Container(),
            ),
        );
    }
}

 

3. 디자인 관련 위젯

 - 배경을 추가하거나 간격을 추가하거나 패딩을 추가하는 등 디자인적인 요소를 적용

 

3-1. Container 위젯

 - 말 그대로 다른 위젯을 담는데 사용.

 - 너비와 높이를 지정하거나 배경, 테두리를 추가할 때 사용

Container(
	decoration: BoxDecoration(
    	color: Colors.red,
        border: Border.all(
        	width: 16.0,
            color: Colors.black,
        ),
        borderRadius: BorderRadius.circular(
        	16.0,
        ),
    ),
    height: 200.0,
    width: 100.0,
)

 

3-2. SizedBox 위젯

 - 일반적으로 일정 크기의 공간을 공백으로 두고 싶을 때 사용

 - Container 위젯을 사용해도 공백을 만들 수 있지만 SizedBox 는 const 생성자를 사용했을 때 성능상의 이점을 얻을 수 있음.

SizedBox(
	height: 200.0,
    width: 200.0,
    
    // 크기를 확인하는 예제로 Container 추가.
    child: Container(
    	color: Colors.red,
    ),
)

 

3-3. Padding 위젯

 - child 위젯에 여백을 제공할 때 사용

 - Padding 위젯의 상위 위젯과 하위 위젯 사이의 여백을 둘 수 있음.

Container(
	color: Colors.blue,
    child: Padding(
    	padding: EdgeInsets.all(
        	16.0,
        ),
        child: Container(
        	color: Colors.red,
            width: 50.0,
            height: 50.0,
        ),
    ),
)

 

Margin 과 Padding 같이 사용하는 예제

// 최상위 Container : margin 이 적용되는 대상)
Container(
	color: Colors.black,
    child: Container(
    	color: Colors.blue,
        
        // margin 적용 위치
        margin: EdgeInsets.all(16.0),
        
        // padding 적용
        child: Padding(
        	padding: EdgeInsets.all(16.0),
            
            // padding 이 적용된 Container
            child: Container(
            	color: Colors.red,
                width: 50,
                height: 50,
            ),
        ),
    ),
)

 

3-4. SafeArea 위젯

 - 기기별로 예외 처리를 하지 않고도 안전한 화면에서만 위젯을 그릴 수 있음.

SafeArea(
	// true 이면 적용 : 안전한 영역만 사용(노치 영역을 사용하지 않음)
    // false 이면 미적용: 안전하지 않은 영역까지 사용(노치 영역을 고려하지 않고 사용)
	top: true,
    bottom: true,
    left: true,
    right: true,
    child: Container(
    	color: Colors.red,
        height: 300.0,
        width: 300.0,
    ),
)

 

 

4. 배치 관련 위젯

 - 하위 위젯을 가로 또는 세로로 배치하거나 위젯 위에 위젯을 겹칠 때 사용

 

4-1. Row 위젯

 - 가로로 위젯을 배치

 - 여러개의 child 위젯을 입력 받을 수 있는 children 매개변수 사용.

import 'package:flutter/material.dart';

class RowWidgetExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SizedBox(
          height: double.infinity,
          child: Row(
            // 주축 정렬 지정
            mainAxisAlignment: MainAxisAlignment.start,
            // 반대축 정렬 지정
            crossAxisAlignment: CrossAxisAlignment.center,
            // 넣고 싶은 위젯 입력
            children: [
              Container(
                height: 50.0,
                width: 50.0,
                color: Colors.red,
              ),
              // SizedBox는 일반적으로 공백을
              // 생성할 때 사용
              const SizedBox(width: 12.0),
              Container(
                height: 50.0,
                width: 50.0,
                color: Colors.green,
              ),
              const SizedBox(width: 12.0),
              Container(
                height: 50.0,
                width: 50.0,
                color: Colors.blue,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

4-2. Column 위젯

 - 세로로 위젯을 배치

import 'package:flutter/material.dart';

class ColumnWidgetExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SizedBox(
          width: double.infinity,
          child: Column(
            // 주축 정렬 지정
            mainAxisAlignment: MainAxisAlignment.start,
            // 반대축 정렬 지정
            crossAxisAlignment: CrossAxisAlignment.start,
            // 넣고 싶은 위젯 입력
            children: [
              Container(
                height: 50.0,
                width: 50.0,
                color: Colors.red,
              ),
              // SizedBox는 일반적으로 공백을 생성할 때 사용
              const SizedBox(width: 12.0),
              Container(
                height: 50.0,
                width: 50.0,
                color: Colors.green,
              ),
              const SizedBox(width: 12.0),
              Container(
                height: 50.0,
                width: 50.0,
                color: Colors.blue,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

4-3. Flexible 위젯

 - Row 나 Column 에서 사용하는 위젯.

 - Flexible 에서 제공된 child 크기를 최소한으로 차지하게 함.

import 'package:flutter/material.dart';

class FlexibleWidgetExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
              Flexible(
                // flex는 남은 공간을 차지할 비율을 의미합니다.
                // flex값을 값을 제공하지 않으면 기본값은 1입니다.
                flex: 1,

                // 파란색 Container
                child: Container(
                  color: Colors.blue,
                ),
              ),
              Flexible(
                flex: 1,

                // 빨간색 Container
                child: Container(
                  color: Colors.red,
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

 

4-4. Expanded 위젯

 - Flexible 위젯을 상속하는 위젯.

 - Expanded 를 사용하면 위젯이 남아있는 공간을 최대한으로 차지.

import 'package:flutter/material.dart';

class ExpandedWidgetExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
              Expanded(
                child: Container(
                  color: Colors.blue,
                ),
              ),
              Expanded(
                child: Container(
                  color: Colors.red,
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

 

4-5. Stack 위젯

 - 위젯을 겹치는 기능

 - 플러터의 그래픽 엔진인 스키아 엔진은 2D 엔진이기 때문에 겹친 두께를 표현하지는 못하지만 Stack 위젯을 사용하면 위젯 위에 위젯을 올린 듯한 효과를 줄 수 있음.

import 'package:flutter/material.dart';

class StackWidgetExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Stack(
            children: [
              Container(
                height: 300.0,
                width: 300.0,
                color: Colors.red,
              ),
              Container(
                height: 250.0,
                width: 250.0,
                color: Colors.yellow,
              ),
              Container(
                height: 200.0,
                width: 200.0,
                color: Colors.blue,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

반응형
반응형

Everything is a Widget.

플러터는 화면에 그려지는 모든 요소가 위젯으로 구성되어 있다.

자주 사용하는 위젯으로 텍스트, 제스처, 디자인. 배치 관련 위젯 등이 있다.

위젯은 현재 주어진 state 를 기반으로 어떤 UI 를 구현할지 정의한다.

state 가 변경되면 기존 위젯의 state 와 새로운 위젯의 state 를 비교하여 UI 변화를 반영할때 최소한 변경 사항을 산출하여 화면을 그려낸다.

자식(child)를 하나만 갖는 위젯

 - Container 위젯 : 자식을 담는 컨테이너 역할. 배경색, 너비와 높이, 테두리등의 디자인을 지정.

 - GestureDetector 위젯 : 제스처 기능을 자식 위젯에서 인식하는 위젯. 탭, 드래그, 더블클릭 등 제스처 기능이 자식 위젯에서 인식되었을 때 함수 실행.

 - SizeBox 위젯 : 높이와 너비를 지정하는 위젯. Container 위젯과 다르게 디자인적인 요소는 적용할 수 없고 const 생성자로 선언할 수 있어서 퍼포먼스 측면에서 더 효율적이다.

 

다수의 자식(child)를 입력 할 수 있는 위젯

 - Column 위젯 : children 매개변수에 입력된 모든 위젯들을 세로로 배치.

 -Row 위젯 :  children 매개변수에 입력된 모든 위젯들을 가로로 배치.

 - ListView 위젯 : 리스트를 구현할 때 사용. children 매개변수에 다수의 위젯을 입력할 수 있으며 입력된 위젯이 화면을 벗어나게되면 스크롤이 가능해진다.

반응형

+ Recent posts