5 minute read


플러터 앱은 위젯을 기반으로 구성된다. 위젯은 앱의 UI를 구축하는 기본 단위이며 플러터 앱의 시각적인 요소를 표현한다. 따라서 플러터에서 버튼이나 텍스트, 이미지 등 UI의 모든 요소는 위젯이라고 할 수 있다.

이 위젯의 종류와 쓰임에 대해서 알아보도록 하자.


1. Text Widget

1.1 Text

화면에 텍스트를 보여주기 위해 사용하는 위젯

1
2
3
4
5
6
7
8
Text(
    //style 설정
    style: TextStyle(
        fontSize: 10.0,
        fontWeight: FontWeight.w700,
        color: Colors.blue,
    ),
)



2. Button Widget

2.1 TextButton

테두리가 없고 텍스트만 있는 버튼

1
2
3
4
5
6
7
8
9
TextButton(
    onPressed: () {
        print('click');
    },
    style: TextButton.styleForm(
        foregroundColor: Colors.red,
        child: Text('text Button'),
    ),
)


2.2 OutlineButton

테두리가 있는 버튼

1
2
3
4
5
6
7
8
9
OutlineButton(
    onPressed: () {
        print('click');
    },
    style: OutlineButton.styleForm(
        foregroundColor: Colors.red,
    ),
    child: Text('outline Text Button'),
)


2.3 ElevatedButton

입체감이 있는 버튼

1
2
3
4
5
6
7
8
9
ElevatedButton(
    onPressed: () {
        print('click');
    },
    style: ElevatedButton.styleForm(
        backgroundColor: Colors.red,
    ),
    child: Text('elevated Button'),
)


2.4 IconButton

이미지 적용이 가능한 버튼

1
2
3
4
5
6
7
8
9
10
IconButton(
    onPressed: () {
        print('click');
    },
    icon: Icon(
        Icons.menu
    ),
    tooltip : 'menu',
    color: Colors.blue,
)


2.5 FloatingActionButton

화면 우측 하단에 나타나는 플로팅 버튼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import 'package:flutter/material.dart'

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

class ExFloatingButton extends StatelessWidget {
	@override
	Widget build(BuildContext context) {
		return MateralApp(
			home: Scaffold(
				floatingActionButton: FloatingActionButton(
					onPressed: (){
						print('click')
					},
					child: Text('floation Button'),
				),
				body: Container(),
			),
		);
	}
}



3. GestureDetector Widget

제스처를 통한 입력을 인식하는 위젯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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,
    ),
)



4. 배치 관련 Widget

4.1 정렬 옵션

4.1.1 MainAxisAlignment - 주축정렬

옵션 설명
start 시작위치 정렬
end 끝위치 정렬
center 중앙정렬
spaceBetween 위젯과 위젯의 사이가 동일하도록 배치
spaceEvenly Between과 성질은 같지만 양 끝도 빈 간격으로 시작
spaceAround spcaeEvenly와 같지만 양 끝이 1/2의 빈간격으로 시작


4.1.2 crossAxisAlignment - 반대축 정렬

옵션 설명
start 시작위치 정렬
end 끝위치 정렬
center 중앙정렬
stretch 최대한으로 늘림


4.1.3 MainAxisSize - 주축 크기

옵션 설명
min 최대 크기
max 최소 크기


4.2 Row

위젯을 가로로 배치하는 위젯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//화면 상단에 container가 가로로 나타나고
//MainAxisAligment.spaceAround 옵션으로 인해 동일 간격으로 정렬된다.
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
			child: Row(
				mainAxisAlignment: MainAxisAlignment.spaceAround,
				children: [
					Container(
						color: Colors.red,
						width: 50.0,
						height: 50.0,
					),
					Container(
						color: Colors.orange,
						width: 50.0,
						height: 50.0,
					),
					Container(
						color: Colors.yellow,
						width: 50.0,
						height: 50.0,
					),
				],
			),
		)
    );
  }
}


4.3 Column

위젯을 세로로 배치하는 위젯

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//화면 상단에 container가 세로로 나타나고
//MainAxisAligment.spaceBetween 옵션으로 양끝에 공백이 없는 간격으로 정렬된다.
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
			child: Column(
				mainAxisAlignment: MainAxisAlignment.spaceBetween,
				children: [
					Container(
						color: Colors.red,
						width: 50.0,
						height: 50.0,
					),
					Container(
						color: Colors.orange,
						width: 50.0,
						height: 50.0,
					),
					Container(
						color: Colors.yellow,
						width: 50.0,
						height: 50.0,
					),
				],
			),
		)
    );
  }
}

** Column과 Row를 이용해 위젯을 정중앙으로 정렬할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import 'package:flutter/material.dart';

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
		body: SafeArea(
			child: Column(
				mainAxisAlignment: MainAxisAlignment.center,
				children: [
					Row(
						mainAxisAlignment: MainAxisAlignment.center,
						children: [
							Container(
								color: Colors.red,
								width: 50.0,
								height: 50.0,
							),
						]
					),
				],
			),
		)
    );
  }
}


4.4 Flexible

Row 또는 Column의 children 에서 사용이 가능하며 남은 공간을 차지할 비율을 설정한다. 값을 따로 설정하지 않으면 기본 값은 1이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import 'package:flutter/material.dart';

class ExFlexible extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
				//아래와 같이 2개의 Container를 flex 1,2 비율로 설정하면
				//화면을 3등분해서 파랑, 빨강 컨테이너가 1:2비율로 나눠진다.
				Flexible(
					flex: 1,
					child: Container(
					color: Colors.blue,
					),
				),
				Flexible(
					flex: 2,
					child: Container(
					color: Colors.red,
					),
				)
            ],
          ),
        ),
      ),
    );
  }
}


4.5 Expanded

Flexible과 마찬가지로 Row나 Column의 children에서만 사용이 가능하고 남아있는 위젯의 공간을 최대한으로 차지한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import 'package:flutter/material.dart';

class ExExpanded extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Column(
            children: [
				//화면을 3가지 색상으로 나눠 채운다.
				Expanded(
					child: Container(
					color: Colors.orange,
					),
				),
				Expanded(
					child: Container(
					color: Colors.yellow,
					),
				),
				Expanded(
					child: Container(
					color: Colors.green,
					),
				)
            ],
          ),
        ),
      ),
    );
  }
}