๋ ์ด์์ ์์ ฏ - Row, Column, Stack, Expanded
์ง๋ ๊ธ์์ ์์ ฏ์ด ํธ๋ฆฌ๋ก ์ด์ด์ง๋ค๋ ๊ฑธ ๋ดค์ผ๋, ์ด๋ฒ์ ์์ ฏ์ ๊ฐ๋ก, ์ธ๋ก, ๊ฒน์ณ์ ๋ฐฐ์นํ๋ ๋ฐฉ๋ฒ์ด๋ค. Compose์ Row, Column, Box์ SwiftUI์ HStack, VStack, ZStack์ ํด๋นํ๋ ์์ ฏ์ด Flutter์๋ ์๋ค. ์ด๋ฆ์ด ๋น์ทํด์ ๊ทธ๋๋ก ์ฐ๋ฉด ๋ ๊ฒ ๊ฐ์๋ฐ, ๊ฐ๋ก๋ก ๊ธด ๊ธ์๋ฅผ ๋ฃ๋ ์๊ฐ ๋ฐ๋ก ๋งํ๋ค.
Row(
children: [
const Icon(Icons.person),
const Text('์์ฃผ์์ฃผ์์ฃผ ๊ธด ์ฌ์ฉ์ ์ด๋ฆ์ด ๋ค์ด๊ฐ๋ ์๋ฆฌ์
๋๋ค ์์ฃผ์์ฃผ ๊ธธ์ด์'),
const Icon(Icons.chevron_right),
],
)์คํํ๋ฉด ํ๋ฉด ์ค๋ฅธ์ชฝ์ ๋ ธ๋-๊ฒ์ ์ค๋ฌด๋ฌ๊ฐ ์๊ธฐ๊ณ , ์ฝ์์ ์ด๋ฐ ์๋ฌ๊ฐ ์ฐํ๋ค.
A RenderFlex overflowed by 182 pixels on the right.Compose์๋ค๋ฉด ๊ธ์๊ฐ ์์์ ์ค์ด๋ค๊ฑฐ๋ ์ค๋ฐ๊ฟ์ด ๋์ ํ ๋ฐ, ์ ํ๋ฉด ๋ฐ์ผ๋ก ๋์น ๊น?
์์ธ: Row๋ ์์์๊ฒ "์ํ๋ ๋งํผ ๊ฐ๋ก๋ก ์ปค์ ธ๋ ๋๋ค"๊ณ ๋งํ๋ค
Flutter ๋ ์ด์์์ ํ ์ค๋ก ์์ฝ๋๋ค. "์ ์ฝ์ ์๋๋ก ๋ด๋ ค๊ฐ๊ณ , ํฌ๊ธฐ๋ ์๋ก ์ฌ๋ผ์จ๋ค." ๋ถ๋ชจ๊ฐ ์์์๊ฒ "๋๋ ์ด ๋ฒ์ ์์์ ํฌ๊ธฐ๋ฅผ ์ ํด๋ผ"๋ผ๋ ์ ์ฝ์ ๋ด๋ ค์ฃผ๊ณ , ์์์ ๊ทธ ์์์ ์๊ธฐ ํฌ๊ธฐ๋ฅผ ์ ํด ๋ถ๋ชจ์๊ฒ ์๋ ค์ค๋ค.
Row๋ ๊ฐ๋ก ๋ฐฉํฅ์ผ๋ก ์์์ ๋์ด๋๋๋ฐ, ์์๋ค์๊ฒ ๊ฐ๋ก ๋ฐฉํฅ ํฌ๊ธฐ ์ ํ์ ์ฃผ์ง ์๋๋ค. ๊ทธ๋์ Text๋ "๊ธ์ ๊ธธ์ด๋งํผ" ํฌ๊ธฐ๋ฅผ ์ก์๋ฒ๋ฆฌ๊ณ , ํฉ์ด ํ๋ฉด ํญ์ ๋์ผ๋ฉด overflowed ์๋ฌ๊ฐ ๋๋ค. ๊ธ์๋ฅผ ์ค๋ฐ๊ฟํ๋ ค๋ฉด "๋๋ ๋จ์ ํญ๊น์ง๋ง ์จ๋ผ"๋ผ๋ ์ ํ์ ๊ฑธ์ด์ค์ผ ํ๋ค.
ํด๊ฒฐ: Expanded๋ก ๋จ์ ๊ณต๊ฐ์ ๋๋ ์ค๋ค
Row(
children: [
const Icon(Icons.person),
const Expanded(
child: Text('์์ฃผ์์ฃผ์์ฃผ ๊ธด ์ฌ์ฉ์ ์ด๋ฆ์ด ๋ค์ด๊ฐ๋ ์๋ฆฌ์
๋๋ค ์์ฃผ์์ฃผ ๊ธธ์ด์'),
),
const Icon(Icons.chevron_right),
],
)Expanded๋ **"์์ด์ฝ ๋ ๊ฐ๊ฐ ์ฐ๊ณ ๋จ์ ๊ณต๊ฐ์ ์ ๋ถ ์ด ์์์๊ฒ ์ค๋ค"**๋ ์์ ฏ์ด๋ค. ์ด์ Text๋ ๋จ์ ํญ ์์์ ์ค๋ฐ๊ฟ๋๊ณ ์๋ฌ๊ฐ ์ฌ๋ผ์ง๋ค. Expanded๋ ์์ ฏ์ด๋ผ Text๋ฅผ ๊ฐ์ธ๋ ๋ฐฉ์์ผ๋ก ์ด๋ค.
๋น์จ๋ก ๋๋๋ ๊ฒ๋ ๋๋ค.
Row(
children: [
Expanded(flex: 1, child: Container(color: Colors.red, height: 50)),
Expanded(flex: 2, child: Container(color: Colors.blue, height: 50)),
],
)flex๊ฐ ๋น์จ์ด๋ผ ๋นจ๊ฐ์ด 1/3, ํ๋์ด 2/3๋ฅผ ์ฐจ์งํ๋ค. Compose์ Modifier.weight(1f), weight(2f)์ ๊ฐ๋ค.
Expanded๋ฅผ ์๋ฌด ๋ฐ๋ ์ฐ๋ฉด ์๋ฌ๊ฐ ๋๋ค
Container(
child: Expanded( // ์ฌ๊ธฐ์ ์๋ฌ๋จ
child: Text('์๋
'),
),
)Incorrect use of ParentDataWidget.Expanded๋ Row, Column, Flex์ ์ง์ ์์์ผ๋ก๋ง ์ธ ์ ์๋ค. "๋จ์ ๊ณต๊ฐ"์ด๋ผ๋ ๊ฐ๋
์ด Row/Column์ฒ๋ผ ํ ๋ฐฉํฅ์ผ๋ก ๋์ด๋๋ ๋ถ๋ชจ์๊ฒ๋ง ์๊ธฐ ๋๋ฌธ์ด๋ค. Container ์์ ๋ฃ์ผ๋ฉด ๋๋ ์ค ๊ณต๊ฐ์ด ์์ด์ ์๋ฌ๊ฐ ๋๋ค. ์ฌ์ด์ ๋ค๋ฅธ ์์ ฏ(Padding ๋ฑ)์ ๋ผ์๋ ๊ฐ์ ์๋ฌ๊ฐ ๋๋ค.
Expanded์ Flexible์ ์ฐจ์ด
Row(
children: [
Flexible(child: Text('์งง์ ๊ธ')), // ํ์ํ ๋งํผ๋ง ์ฐ๊ณ , ๋์น๋ฉด ์ค์ด๋ฆ
Expanded(child: Text('์งง์ ๊ธ')), // ๋จ์ ๊ณต๊ฐ์ ๋ฌด์กฐ๊ฑด ๋ค ์ฑ์
],
)Expanded๋ ์ฌ์ค Flexible(fit: FlexFit.tight)์ ์ค์๋ง์ด๋ค. Flexible์ ์์์ด ์์ผ๋ฉด ์์ ๋๋ก ๋๊ณ , ํด ๋๋ง ์ค์ฌ์ค๋ค. ๋จ์ ๊ณต๊ฐ์ ๊ฝ ์ฑ์์ผ ํ๋ฉด Expanded, ๋์น์ง๋ง ์๊ฒ ํ๋ ค๋ฉด Flexible์ ์ด๋ค.
Row์ Column ์ ๋ ฌ: ์ฃผ์ถ๊ณผ ๊ต์ฐจ์ถ
Column์ ์ธ๋ก๋ก ๋์ด๋๋ ์์ ฏ์ด๊ณ , ์ ๋ ฌ์ ๋ ๋ฐฉํฅ์ผ๋ก ๋๋๋ค.
Column(
mainAxisAlignment: MainAxisAlignment.center, // ์ฃผ์ถ(์ธ๋ก) ์ ๋ ฌ
crossAxisAlignment: CrossAxisAlignment.start, // ๊ต์ฐจ์ถ(๊ฐ๋ก) ์ ๋ ฌ
children: [
Text('์ ๋ชฉ'),
Text('๋ด์ฉ'),
],
)- ์ฃผ์ถ(main axis): ์์์ด ๋์ด์๋ ๋ฐฉํฅ.
Column์ ์ธ๋ก,Row๋ ๊ฐ๋ก - ๊ต์ฐจ์ถ(cross axis): ๊ทธ ์์ง ๋ฐฉํฅ.
Column์ ๊ฐ๋ก,Row๋ ์ธ๋ก
Row๋ก ๋ฐ๊พธ๋ฉด ๋ ์ถ์ ๋ฐฉํฅ์ด ์๋ก ๋ค๋ฐ๋๋ค. "๊ฐ๋ก ์ ๋ ฌ์ ์ด๊ฑฐ, ์ธ๋ก ์ ๋ ฌ์ ์ ๊ฑฐ"๋ก ์ธ์ฐ์ง ๋ง๊ณ **"๋์ด์๋ ๋ฐฉํฅ์ด ์ฃผ์ถ"**์ผ๋ก ๊ธฐ์ตํด์ผ ํท๊ฐ๋ฆฌ์ง ์๋๋ค.
๊ฐ | ์ฃผ์ถ์์์ ์๋ฏธ |
| ์์ ์ชฝ์ผ๋ก ๋ชฐ๊ธฐ |
| ๊ฐ์ด๋ฐ |
| ๋ ์ชฝ์ผ๋ก ๋ชฐ๊ธฐ |
| ์ ๋์ ๋ถ์ด๊ณ ์ฌ์ด๋ฅผ ๊ท ๋ฑํ๊ฒ |
| ๋ชจ๋ ๊ฐ๊ฒฉ(์ ๋ ํฌํจ)์ ๊ท ๋ฑํ๊ฒ |
Stack: ๊ฒน์ณ ๋๊ธฐ
Stack์ ์์์ ์๋ก ์๋๋ค. ๋จผ์ ์ด ์์์ด ์๋, ๋์ค์ ์ด ์์์ด ์์ ๊ทธ๋ ค์ง๋ค.
Stack(
children: [
Container(width: 200, height: 200, color: Colors.blue),
Positioned(
right: 8,
bottom: 8,
child: const Text('์ฐํ๋จ ๊ธ์', style: TextStyle(color: Colors.white)),
),
],
)Positioned๋ Stack์ ์์์ "์ผ์ชฝ์์ ์ผ๋ง, ์๋์์ ์ผ๋ง" ์์ผ๋ก ์์น๋ฅผ ์ง์ ํ๋ ์์ ฏ์ด๋ค. ์ด๊ฒ๋ Expanded์ฒ๋ผ Stack์ ์ง์ ์์์ผ ๋๋ง ์ธ ์ ์๋ค. ์์น๋ฅผ ์ง์ ํ์ง ์์ ์์์ alignment(๊ธฐ๋ณธ๊ฐ์ ์ผ์ชฝ ์)์ ๋ฐ๋ผ ๋์ธ๋ค.
Stack(
alignment: Alignment.center, // ์์น ์ง์ ์๋ ์์์ ๊ฐ์ด๋ฐ๋ก
children: [...],
)ํ๋กํ ์ฌ์ง ์์ ๋ฐฐ์ง๋ฅผ ์ฌ๋ฆฌ๊ฑฐ๋, ์ด๋ฏธ์ง ์์ ๊ธ์๋ฅผ ์น์ ๋ ์ด๋ค.
Compose, SwiftUI์ ๋น๊ตํ๋ฉด
// Compose
Row(horizontalArrangement = Arrangement.SpaceBetween) {
Icon(...)
Text("์ด๋ฆ", modifier = Modifier.weight(1f))
}// SwiftUI
HStack {
Image(systemName: "person")
Text("์ด๋ฆ").frame(maxWidth: .infinity)
}ํ๊ณ ์ถ์ ๊ฒ | Flutter | Compose | SwiftUI |
๊ฐ๋ก๋ก ๋ฐฐ์น |
|
|
|
์ธ๋ก๋ก ๋ฐฐ์น |
|
|
|
๊ฒน์ณ์ ๋ฐฐ์น |
|
|
|
๋จ์ ๊ณต๊ฐ ์ฐจ์ง |
|
|
|
๋น์จ ๋๋๊ธฐ |
|
| ์ง์ ๊ณ์ฐ ํ์ |
์ ๋ ฌ ์ง์ |
|
|
|
์์น ์ง์ |
|
|
|
๊ฐ์ฅ ํฐ ์ฐจ์ด๋ "๋จ์ ๊ณต๊ฐ ์ฐจ์ง"๊ฐ ์์ฑ์ด ์๋๋ผ ์์ ฏ์ผ๋ก ๊ฐ์ธ๋ ๋ฐฉ์์ด๋ผ๋ ์ ์ด๋ค. Compose๋ Modifier๋ฅผ ๋ถ์ด๊ณ , Flutter๋ Expanded๋ก ๊ฐ์ผ๋ค. ์ง๋ ๊ธ์์ Center๊ฐ ์์ ฏ์ด๋ผ๊ณ ํ๋ ๊ฒ๊ณผ ๊ฐ์ ๋ฐ์์ด๋ค.
์ ๋ฆฌ
- Flutter ๋ ์ด์์์ "์ ์ฝ์ ์๋๋ก, ํฌ๊ธฐ๋ ์๋ก" ํ๋ฅด๊ณ ,
Row/Column์ ์์์๊ฒ ์ฃผ์ถ ๋ฐฉํฅ ํฌ๊ธฐ ์ ํ์ ์ฃผ์ง ์๋๋ค - ๊ธด ๊ธ์๊ฐ
overflowed์๋ฌ๋ฅผ ๋ด๋ฉดExpanded๋Flexible๋ก ๊ฐ์ธ์ ๋จ์ ๊ณต๊ฐ ์์์ ํฌ๊ธฐ๋ฅผ ์ ํ๊ฒ ํ๋ค Expanded๋Row/Column์ ์ง์ ์์์ผ๋ก๋ง,Positioned๋Stack์ ์ง์ ์์์ผ๋ก๋ง ์ธ ์ ์๋ค- ์ ๋ ฌ์ ๋์ด์๋ ๋ฐฉํฅ์ด ์ฃผ์ถ(
mainAxisAlignment), ๊ทธ ์์ง ๋ฐฉํฅ์ด ๊ต์ฐจ์ถ(crossAxisAlignment)์ด๋ค Stack์ ์์์ ๊ฒน์ณ ์๊ณ , ์์น๋ฅผ ์ ํ๊ณ ์ถ์ผ๋ฉดPositioned๋ฅผ ์ด๋ค- Compose์
Row/Column/Box, SwiftUI์HStack/VStack/ZStack๊ณผ 1:1๋ก ๋์ํ์ง๋ง, ํฌ๊ธฐ ์กฐ์ ์ ์์ ฏ์ผ๋ก ๊ฐ์ธ์ ํ๋ค๋ ์ ์ด ๋ค๋ฅด๋ค
๋ค์ ๊ธ์์๋ ์คํฌ๋กค๋๋ ๋ชฉ๋ก์ ๋ง๋๋ ListView์ GridView๋ฅผ ๋ค๋ค๋ณด๊ฒ ๋ค.
