위젯
위젯이란?
Flutter에서 위젯은 사용자 인터페이스의 기본 구성 요소입니다. Flutter의 모든 것은 위젯으로 구성됩니다. 버튼, 텍스트, 이미지 등 모든 것이 위젯입니다. 위젯은 사용자 인터페이스를 설계하고, 기능을 추가하며, 레이아웃을 관리하는 데 사용됩니다.
위젯의 주요 유형
Flutter에서 위젯은 크게 두 가지 유형으로 나뉩니다:
StatelessWidget
상태를 가지지 않는 정적인 위젯입니다. 한 번 생성되면 변경되지 않습니다.
- 사용 예: 단순 텍스트, 아이콘 또는 기본 레이아웃 구성.
StatefulWidget
상태를 가지는 동적인 위젯입니다. 사용자의 상호작용에 따라 UI가 업데이트됩니다.
- 사용 예: 버튼 클릭, 입력 필드, 슬라이더 등 동작이 필요한 UI 요소.
이 문서에서는 Flutter에서 자주 사용되는 주요 위젯에 대해 설명하고, 각 위젯의 사용법과 를 제공합니다.
Flutter 위젯
Container
Container 위젯은 너비와 높이를 지정하거나, 배경 색상이나 테두리를 추가할 때 많이 사용됩니다. 레이아웃을 구성하고 스타일을 적용하는 데 유용합니다
- 주요 속성:
- width: 너비를 지정합니다.
- height: 높이를 지정합니다.
- color: 배경 색상을 지정합니다.
- decoration: 테두리, 그림자, 배경 이미지를 추가할 수 있습니다.
- padding: 내부 여백을 설정합니다.
- margin: 외부 여백을 설정합니다.
- alignment: 자식 위젯의 정렬 방식을 지정합니다.
Container(
width: 200,
height: 100,
color: Colors.blue,
child: Center(
child: Text(
'컨테이너 예제',
style: TextStyle(color: Colors.white),
),
),
);DecoratedBox
자식 위젯에 스타일링을 적용합니다.
Container(
width: 200,
height: 100,
decoration: BoxDecoration(
color: Colors.green,
border: Border.all(color: Colors.black, width: 2),
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.grey,
offset: Offset(4, 4),
blurRadius: 5,
),
],
),
child: Center(
child: Text(
'스타일 적용 컨테이너',
style: TextStyle(color: Colors.white),
),
),
);GestureDetector
플러터에서 제공하는 제스처 기능을 자식 위젯에서 인식하는 위젯입니다. 탭이나 드래그 그리고 더블 클릭 같은 제스처 기능이 자식 위젯에 인식됐을 때 함수를 실행할 수 있습니다.
GestureDetector는 사용자의 제스처(탭, 드래그 등)를 감지하는 데 사용됩니다.
GestureDetector(
onTap: () {
print('위젯이 탭되었습니다!');
},
child: Container(
color: Colors.blue,
padding: EdgeInsets.all(20),
child: Text('탭하세요'),
),
);TextField
사용자 입력을 받기 위한 텍스트 필드입니다.
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: '이름을 입력하세요',
),
onChanged: (text) {
print('입력된 텍스트: $text');
},
);Checkbox
사용자가 "참" 또는 "거짓"을 선택할 수 있도록 하는 체크박스입니다.
bool isChecked = false;
Checkbox(
value: isChecked,
onChanged: (value) {
setState(() {
isChecked = value!;
});
},
);Slider
슬라이더는 사용자가 드래그를 통해 값을 선택할 수 있게 합니다.
Slider(
value: _currentSliderValue,
min: 0,
max: 100,
divisions: 10,
label: _currentSliderValue.round().toString(),
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
});
},
);Column
Column 위젯은 자식 위젯들을 세로 방향으로 배치합니다.
Column(
children: [
Text('첫 번째'),
Text('두 번째'),
Text('세 번째'),
],
);MainAxisAlignment 옵션 (모든 는 CrossAxisAlignment.center 기준입니다)
MainAxisAlignment.start: 위쪽 정렬
Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text('첫 번째'),
Text('두 번째'),
Text('세 번째'),
],
);MainAxisAlignment.center: 중앙 정렬
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('첫 번째'),
Text('두 번째'),
Text('세 번째'),
],
);MainAxisAlignment.end: 아래쪽 정렬
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('첫 번째'),
Text('두 번째'),
Text('세 번째'),
],
);Row
Row 위젯은 자식 위젯들을 가로 방향으로 배치합니다.
Row(
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);MainAxisAlignment 옵션 (모든 는 CrossAxisAlignment.center 기준)
MainAxisAlignment.start: 왼쪽 정렬
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);MainAxisAlignment.center: 중앙 정렬
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);MainAxisAlignment.end: 오른쪽 정렬
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);MainAxisAlignment.spaceBetween: 위젯 간 간격 동일
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);MainAxisAlignment.spaceAround: 위젯 간과 바깥 간격 동일
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);MainAxisAlignment.spaceEvenly: 위젯 간 및 바깥 간격 균등
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(Icons.star),
Icon(Icons.favorite),
Icon(Icons.home),
],
);SafeArea
SafeArea 위젯은 장치의 상단, 하단, 또는 측면의 안전 영역(예: 노치, 상태 표시줄)을 고려하여 UI를 배치할 때 사용됩니다. 이 위젯은 UI가 잘리지 않도록 보장합니다.
SafeArea(
child: Text('안전한 영역에 위치합니다!'),
);Flexible
Flexible 위젯은 Row나 Column에서 사용하는 위젯입니다. Flexible 위젯을 Column과 Row에서 사용하면 Flexible에 제공된 child가 크기를 최소한으로 차지하게 할 수 있습니다. 추가적으로 flex 매개변수를 이용해 각 Flexible 위젯이 얼만큼의 비율로 공간을 차지할지 지정할 수도 있습니다.
Row(
children: [
Flexible(
flex: 1,
child: Container(color: Colors.red),
),
Flexible(
flex: 2,
child: Container(color: Colors.blue),
),
],
);Expanded
Expanded 위젯은 Row나 Column 내에서 사용되며, 남은 공간을 자식 위젯이 균등하게 채우도록 설정할 때 유용합니다. Expanded 위젯은 Flexible을 확장한 형태로, flex 매개변수를 통해 공간 비율을 조정할 수도 있습니다.
Row(
children: [
Expanded(
child: Container(color: Colors.red),
),
Expanded(
child: Container(color: Colors.blue),
),
],
);SizedBox
SizedBox 위젯은 고정된 크기의 빈 공간을 만들거나 자식 위젯의 크기를 지정할 때 사용됩니다. SizedBox는 레이아웃을 미세 조정할 때 특히 유용합니다.
SizedBox(
width: 50,
height: 50,
child: Container(color: Colors.green),
);BoxFit
BoxFit 위젯은 이미지 또는 자식 위젯이 부모 컨테이너 안에서 어떻게 맞춰질지를 결정하는 데 사용됩니다. 다양한 옵션을 제공하여 원하는 방식으로 조정할 수 있습니다.
- 옵션:
- BoxFit.fill: 이미지를 컨테이너 크기에 맞게 채웁니다.
- BoxFit.contain: 비율을 유지하며 컨테이너 안에 맞춥니다.
- BoxFit.cover: 비율을 유지하며 컨테이너를 덮습니다.
- BoxFit.fitWidth: 가로를 기준으로 비율을 유지합니다.
- BoxFit.fitHeight: 세로를 기준으로 비율을 유지합니다.
- BoxFit.none: 크기를 조정하지 않습니다.

Image.asset(
'assets/image.png',
fit: BoxFit.cover,
);Stack
위젯을 겹치는 기능을 제공해줍니다. 플러터의 그래픽 엔진인 스키아 엔진은 2D 엔진이기 때문에 겹친 두께를 표현하지는 못하지만 Stack을 사용하면 위젯 위에 위젯을 올린 듯한 효과를 줄 수 있습니다.
자식 위젯들을 서로 겹치도록 배열합니다.
Stack(
children: [
Container(color: Colors.red, width: 100, height: 100),
Container(color: Colors.green, width: 50, height: 50),
],
);GridView
자식 위젯들을 그리드(격자) 형태로 배열합니다.
GridView.count(
crossAxisCount: 2,
children: [
Container(color: Colors.red),
Container(color: Colors.green),
Container(color: Colors.blue),
Container(color: Colors.yellow),
],
);Padding
자식 위젯에 여백을 추가합니다.
Padding(
padding: EdgeInsets.all(20),
child: Text('패딩이 추가된 텍스트!'),
);Align
자식 위젯을 컨테이너 내에서 특정 위치로 정렬합니다.
Align(
alignment: Alignment.bottomRight,
child: Text('오른쪽 아래에 위치합니다!'),
);Transform
자식 위젯을 회전, 크기 조정, 또는 기울일 수 있습니다.
Transform.rotate(
angle: 0.5,
child: Container(
width: 100,
height: 100,
color: Colors.green,
),
);Cupertino
iOS 스타일의 위젯을 제공합니다.
CupertinoButton(
child: Text('iOS 스타일 버튼'),
onPressed: () {
print('CupertinoButton 클릭됨');
},
);Material
Android 스타일의 위젯을 제공합니다.
MaterialButton(
onPressed: () {
print('MaterialButton 클릭됨');
},
color: Colors.blue,
child: Text('Material 스타일 버튼'),
);