Flexible
과 Expanded
은 Flutter에서 반응형 어플리케이션을 만들기 위해 사용하는 Widget 입니다.
두 위젯의 목적은 반응형 디자인입니다. 즉, Flutter 앱이 화면 크기에 따라 변경되고 적응하는 것입니다. 두 위젯 모두 Column
과 Row
와 밀접한 연관이 있으며, 상위 Column
과 Row
의 기본축에 연관된 하위 위젯들을 Responsive하게 사이즈를 변경 시켜줍니다.
Flexible
속성
Flexible(
flex: 1, // default
fit: FlexFit.loose, // default
child: Container(),// required field
),
fit
: Column 혹은 Row 기본축의 남은 공간을 어떻게 차지 하게 할 것인지를 정해주는 속성
1. FlexFit.tight
: 기본축의 남은 공간을 전부 채우도록 합니다.
2. FlexFit.loose
: 기본축의 남은 공간을 채우도록 하되 필요한 공간만 차지하도록 합니다.
flex
: Column 혹은 Row 기본축의 남은공간을 flex 값 / 전체 자식들의 flex의 합만큼 차지하도록 합니다.
예제
1. Flexible을 사용하지 않은 위젯이 화면의 크기를 넘어갈 경우
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Container(
width: 600,
height: 100,
color: Colors.green,
),
],
),
위젯이 화면의 크기를 넘어갈 경우, 당연하게도 에러가 발생하게 됩니다.
2. Flexible fit 속성 FlexFit.loose(Default) 사용
Row가 화면의 크기를 넘어갈 경우
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: 600,
height: 100,
color: Colors.green,
),
),
],
)
만약, 화면의 크기를 넘어가는 Row에서 자식 위젯을 Flexible로 위젯을 감쌀 경우, 화면의 남는 필요한 공간만 차지하게 되어 에러발생을 하지 않게됩니다.
Row가 화면의 크기를 안넘을 경우
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: 50,
height: 100,
color: Colors.green,
),
),
],
),
두번째 위젯의 크기가 화면의 크기를 넘어가지 않는다면 필요한 공간만 차지합니다. (wrap_content와 동일하게 작동)
만약, Column이나 Row가 화면의 크기에 따라 넘치거나 할 가능성이 조금이라도 존재한다면 Flexible
을 사용하여 반응형으로 만드는 것이 안전합니다.
3. Flexible fit 속성 FlexFit.tight 사용
Row(
children: [
Container(
width: 100,
height: 100,
color: Colors.blue,
),
Flexible(
fit: FlexFit.tight,
child: Container(
width: 50,
height: 100,
color: Colors.green,
),
),
],
),
FlexFit.tight
를 속성으로 줄 경우, 남은 공간을 전부 차지하게 됩니다.
4. Flexible flex 속성 사용
Row(
children: [
Flexible(
flex: 3,
child: Container(
height: 100,
color: Colors.blue,
),
),
Flexible(
flex: 2,
child: Container(
height: 100,
color: Colors.green,
),
),
Flexible(
flex: 1,
child: Container(
height: 100,
color: Colors.red,
),
),
],
),
남은공간을 파랑, 초록, 빨강이 1/2, 1/3, 1/6 (flex 값 / 전체 자식들의 flex의 합) 비율 만큼 차지하게 됩니다.
Expanded
Expanded
는 Flexible with FlexFit.tight의 줄임말 입니다.
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Expanded(
child: Container(
height: 100,
color: Colors.green,
),
),
],
),
Flexible(FlexFit.tight)
와 동일하게 파란부분이 차지하는 부분 외에 남은 공간을 초록 색상이 차지합니다.
전체코드
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FlexibleExpandedScreen(title: 'Flexible Expanded Example'),
);
}
}
class FlexibleExpandedScreen extends StatefulWidget {
final String title;
FlexibleExpandedScreen({required this.title});
@override
_FlexibleExpandedScreenState createState() => _FlexibleExpandedScreenState();
}
class _FlexibleExpandedScreenState extends State<FlexibleExpandedScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SafeArea(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'overflowed widgets',
style: TextStyle(
fontSize: 16,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Container(
width: 600,
height: 100,
color: Colors.green,
),
],
),
SizedBox(
height: 16.0,
),
Text(
'Flexible FlexFit loose',
style: TextStyle(
fontSize: 16,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: 600,
height: 100,
color: Colors.green,
),
),
],
),
SizedBox(
height: 16.0,
),
Text(
'Flexible FlexFit loose',
style: TextStyle(
fontSize: 16,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Flexible(
fit: FlexFit.loose,
child: Container(
width: 50,
height: 100,
color: Colors.green,
),
),
],
),
SizedBox(
height: 16.0,
),
Text(
'Flexible FlexFit tight',
style: TextStyle(
fontSize: 16,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Container(
width: 100,
height: 100,
color: Colors.blue,
),
Flexible(
fit: FlexFit.tight,
child: Container(
width: 50,
height: 100,
color: Colors.green,
),
),
],
),
SizedBox(
height: 16.0,
),
Text(
'Flexible flex',
style: TextStyle(
fontSize: 16,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Flexible(
flex: 3,
child: Container(
height: 100,
color: Colors.blue,
),
),
Flexible(
flex: 2,
child: Container(
height: 100,
color: Colors.green,
),
),
Flexible(
flex: 1,
child: Container(
height: 100,
color: Colors.red,
),
),
],
),
SizedBox(
height: 16.0,
),
Text(
'Expanded',
style: TextStyle(
fontSize: 16,
),
),
SizedBox(
height: 8.0,
),
Row(
children: [
Container(
width: 300,
height: 100,
color: Colors.blue,
),
Expanded(
child: Container(
height: 100,
color: Colors.green,
),
),
],
),
],
),
),
),
),
);
}
}