Flutter

์ธ๋””์ผ€์ดํ„ฐ์™€ ๋ฒ„ํŠผ ์‚ฌ์ด ๊ฐ„๊ฒฉ์ด ์กฐ์ •๋˜์ง€ ์•Š๋Š” ์ด์Šˆ

flutter developer 2025. 2. 24. 13:31

๐Ÿ˜ญ  ์ธ๋””์ผ€์ดํ„ฐ์™€ ๋ฒ„ํŠผ ์‚ฌ์ด ๊ฐ„๊ฒฉ์ด ์กฐ์ •๋˜์ง€ ์•Š๋Š” ์ด์Šˆ

 

Flutter์˜ PageView์™€ SmoothPageIndicator๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜จ๋ณด๋”ฉ ํ™”๋ฉด์„ ๊ตฌํ˜„ํ•˜๋˜ ์ค‘, ์ธ๋””์ผ€์ดํ„ฐ์™€ ๋ฒ„ํŠผ ์‚ฌ์ด์˜ ๊ฐ„๊ฒฉ์„ ์ค„์ด๋ ค๊ณ  ํ•ด๋„ ๋ณ€๊ฒฝ๋˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

  • Padding.only(bottom: 2)๋กœ ์„ค์ •ํ•ด๋„ ๊ฐ„๊ฒฉ์ด ์ค„์–ด๋“ค์ง€ ์•Š์Œ.
  • SafeArea๋ฅผ ๊ฐ์‹ธ๋Š” ๋ฐฉ์‹ ๋ณ€๊ฒฝ์—๋„ ๋ณ€ํ™” ์—†์Œ.
  • Column ๋‚ด๋ถ€ ์—ฌ๋ฐฑ์ด ์ž๋™์œผ๋กœ ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž„.

๐Ÿ” ์›์ธ ๋ถ„์„: Flutter์˜ Column ๋ฐฐ์น˜ ๋ฐฉ์‹๊ณผ SafeArea์˜ ์˜ํ–ฅ

1. Column์˜ ๊ธฐ๋ณธ์ ์ธ ๋ฐฐ์น˜ ๋ฐฉ์‹

Column(
  children: [
    Expanded(child: PageView(...)), // โœ… PageView๊ฐ€ ํ™•์žฅ๋จ
    _buildPageIndicator(),  // โŒ ์—ฌ๋ฐฑ์ด ์ž๋™์œผ๋กœ ์ถ”๊ฐ€๋จ
    SafeArea(child: _buildBottomButtons()), // โŒ SafeArea๊ฐ€ ์ถ”๊ฐ€ ํŒจ๋”ฉ ์ ์šฉ
  ],
);

Flutter์˜ Column์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ตœ๋Œ€ํ•œ์˜ ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๋ ค๋Š” ์„ฑ์งˆ์ด ์žˆ๋‹ค.
์ฆ‰, mainAxisSize: MainAxisSize.max๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์ด๋ฏ€๋กœ ๋‚ด๋ถ€ ์œ„์ ฏ๋“ค ์‚ฌ์ด์— ๋ถˆํ•„์š”ํ•œ ์—ฌ๋ฐฑ์ด ์ž๋™ ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ๋‹ค.

 

 

2. SafeArea๊ฐ€ ๋ถˆํ•„์š”ํ•œ ํŒจ๋”ฉ์„ ์ถ”๊ฐ€

SafeArea(
  child: Column(
    children: [
      _buildPageIndicator(),
      _buildBottomButtons(),
    ],
  ),
);

SafeArea๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์†Œํ”„ํŠธ ํ‚ค๋ณด๋“œ, ๋„ค๋น„๊ฒŒ์ด์…˜ ๋ฐ”, ์ƒํƒœ ๋ฐ” ๋“ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ์ถ”๊ฐ€์ ์ธ padding์„ ์ ์šฉํ•œ๋‹ค.
์ด๋•Œ, SafeArea๊ฐ€ ์ „์ฒด Column์„ ๊ฐ์‹ธ๊ณ  ์žˆ์œผ๋ฉด ๋ถˆํ•„์š”ํ•œ ์—ฌ๋ฐฑ์ด ์ƒ๊ธฐ๊ฒŒ ๋œ๋‹ค.

 

3. PageView์˜ Expanded ์‚ฌ์šฉ์œผ๋กœ ์ธํ•ด ํ•˜๋‹จ ์š”์†Œ๊ฐ€ ๋ฐ€๋ ค๋‚˜๋Š” ๋ฌธ์ œ

Column(
  children: [
    Expanded(child: PageView(...)), // โœ… PageView๊ฐ€ ์ตœ๋Œ€ํ•œ ํ™•์žฅ๋จ
    _buildPageIndicator(),  // โŒ PageView๊ฐ€ ํ™•์žฅ๋˜๋ฉด์„œ ํ•˜๋‹จ ์š”์†Œ๊ฐ€ ๋ฐ€๋ ค๋‚จ
    _buildBottomButtons(),
  ],
);

Expanded(child: PageView(...))๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด PageView๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๋ ค๊ณ  ํ•˜๋ฉด์„œ, ํ•˜๋‹จ ์ธ๋””์ผ€์ดํ„ฐ์™€ ๋ฒ„ํŠผ์ด ์ž๋™์œผ๋กœ ๋ฐ€๋ ค๋‚˜๋ฒ„๋ฆผ.


mainAxisSize ๋ž€?

MainAixSize๋Š” Cloumn/Row ์œ„์ ฏ์—์„œ ๋ฉ”์ธ์ถ•์˜ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ์ด๋‹ค. 

 

Column(
  mainAxisSize: MainAxisSize.max, // ๊ธฐ๋ณธ๊ฐ’์ด๋ฏ€๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์•„๋„ Max
  children: [
    Container(height: 300, color: Colors.red),
    Container(height: 300, color: Colors.blue),
  ],
),

๋ถ€๋ชจ๊ฐ€ Scaffold๋ผ๋ฉด, Column์€ ์ „์ฒด ํ™”๋ฉด ๋†’์ด๋ฅผ ์ฐจ์ง€ (896px ๊ธฐ์ค€).
→ Container ๋‘ ๊ฐœ์˜ ํ•ฉ์€ 600px์ด์ง€๋งŒ, ๋‚จ์€ ๊ณต๊ฐ„๋„ ์ฐจ์ง€ํ•˜์—ฌ ์ด 896px์ด ๋จ.

 

Column(
  mainAxisSize: MainAxisSize.min,
  children: [
    Container(height: 300, color: Colors.red),
    Container(height: 300, color: Colors.blue),
  ],
),

Column์˜ ๋†’์ด๋Š” 600px๋กœ ์ œํ•œ๋จ.
→ Scaffold์˜ ์ „์ฒด ๋†’์ด(896px)๊ฐ€ ์žˆ๋”๋ผ๋„ Column์€ ์ž์‹ ์œ„์ ฏ๋“ค์˜ ๋†’์ด(600px)๋งŒํผ๋งŒ ์ฐจ์ง€.

→ min์„ ์„ค์ •ํ•˜๋ฉด ์ตœ์†Œ ํฌ๊ธฐ(min)๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ž์‹ ์œ„์ ฏ๋“ค์˜ ํฌ๊ธฐ์— ๋งž๊ฒŒ Column/Row๊ฐ€ ์ถ•์†Œ๋จ


โœ… ํ•ด๊ฒฐ๋œ ์ฝ”๋“œ

Column(
  children: [
    Expanded(
      child: PageView(
        controller: pageController,
        onPageChanged: (index) {
          context.read<OnboardingCubit>().changePage(index);
        },
        children: const [
          OnboardingPage(title: "ํ›ˆ๋ จ ๊ด€๋ฆฌ๋ฅผ ํ•œ ๋ฒˆ์—", description: "ํ›ˆ๋ จ ๊ณ„ํš๋ถ€ํ„ฐ ์Šค์ผ€์ค„ ๊ด€๋ฆฌ๊นŒ์ง€"),
          OnboardingPage(title: "์ถœ๊ฒฐ ๊ด€๋ฆฌ๋„ ๊ฐ„ํŽธํ•˜๊ฒŒ", description: "์ถœ์„ ํ˜„ํ™ฉ ๊ด€๋ฆฌ๋ถ€ํ„ฐ ํšŒ์› ์ •๋ณด ํ™•์ธ๊นŒ์ง€"),
          OnboardingPage(title: "AI๋กœ ๋ถ„์„ํ•˜๋Š” ํ›ˆ๋ จ ํ˜„ํ™ฉ", description: "์ฐธ์—ฌ ๋งŒ์กฑ๋„๋ถ€ํ„ฐ ํ›ˆ๋ จ ํ˜„ํ™ฉ๊นŒ์ง€"),
          OnboardingPage(title: "๋งž์ถคํ˜• ํ›ˆ๋ จ ๋…ธํŠธ", description: "ํ›ˆ๋ จ ๋™์ž‘๋ณ„ ๊ด€๋ฆฌ๋ถ€ํ„ฐ ์‹œํ€€์Šค ๊ตฌ์„ฑ๊นŒ์ง€"),
          OnboardingPage(title: "Your Play\nYour Story", description: ""),
        ],
      ),
    ),
    SafeArea(
      child: Column(
        mainAxisSize: MainAxisSize.min, // โœ… ๋ถˆํ•„์š”ํ•œ ์—ฌ๋ฐฑ ๋ฐฉ์ง€
        children: [
          _buildPageIndicator(pageController), // โœ… ์ธ๋””์ผ€์ดํ„ฐ์™€ ๋ฒ„ํŠผ์„ ํ•˜๋‚˜์˜ Column์œผ๋กœ ๋ฌถ์Œ
          _buildBottomButtons(context),
        ],
      ),
    ),
  ],
);

โœ… Column์˜ mainAxisSize: MainAxisSize.min์„ ์„ค์ •ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์—ฌ๋ฐฑ์„ ์ œ๊ฑฐ

  • ๊ธฐ๋ณธ์ ์œผ๋กœ Column์€ mainAxisSize: MainAxisSize.max์ด๋ฉฐ, ์ด๋กœ ์ธํ•ด ์ž๋™ ์—ฌ๋ฐฑ์ด ์ถ”๊ฐ€๋  ์ˆ˜ ์žˆ์Œ.

โœ… SafeArea๋Š” ํ•˜๋‹จ ๋ฒ„ํŠผ๋งŒ ๊ฐ์‹ธ๋„๋ก ์กฐ์ •

  • SafeArea๊ฐ€ ์ „์ฒด Column์„ ๊ฐ์‹ธ๋ฉด ์ถ”๊ฐ€์ ์ธ padding์ด ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Œ.

โœ… PageView๋ฅผ Expanded ๋Œ€์‹  Flexible๋กœ ๊ฐ์‹ธ ํ•˜๋‹จ ์š”์†Œ๊ฐ€ ๋ฐ€๋ ค๋‚˜๋Š” ํ˜„์ƒ ๋ฐฉ์ง€

  • Expanded๋Š” ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ณต๊ฐ„์„ ์ฐจ์ง€ํ•˜๋ ค ํ•˜์ง€๋งŒ, Flexible์€ ์ ์ ˆํ•œ ๊ณต๊ฐ„๋งŒ ์ฐจ์ง€ํ•˜๋„๋ก ์ œํ•œ.

โœ… UI ๋ฐฐ์น˜ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์•„๋ž˜ ์‚ฌํ•ญ์„ ๋จผ์ € ์ฒดํฌํ•˜์ž!

  • Column ๋‚ด๋ถ€์—์„œ ๋ถˆํ•„์š”ํ•œ ์—ฌ๋ฐฑ์ด ์ถ”๊ฐ€๋˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธ (mainAxisSize: MainAxisSize.min ์ ์šฉ)
  • SafeArea๊ฐ€ ๋ถˆํ•„์š”ํ•œ padding์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธ
  • PageView๊ฐ€ Expanded๋กœ ์ธํ•ด ํ•˜๋‹จ ์š”์†Œ๋ฅผ ๋ฐ€์–ด๋‚ด๊ณ  ์žˆ์ง€ ์•Š์€์ง€ ํ™•์ธ
  • Padding์ด ์˜๋„ํ•œ ๊ฐ’๋ณด๋‹ค ํฌ๊ฒŒ ์ ์šฉ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธ