Foggy day

[Flutter] Scaffold Widget - 사용법 본문

Flutter/Flutter widget

[Flutter] Scaffold Widget - 사용법

jinhan38 2023. 3. 27. 22:21

 

 

이번 포스팅에서는 Scaffold 위젯에 대해 알아보겠습니다. 

 

 

Scaffold 위젯은 대부분의 화면에서 가장 상위 레벨에서 사용하는 위젯입니다. 사실 Scaffold 위젯은 MaterialApp의 탑 레벨 위젯으로 사용되기 위해 고안된 위젯입니다. Scaffold 위젯이 가지고 있는 기능들을 한 페이지에서 모두 다루기는 어려울 것 같습니다. 때문에 AppBar, BottomNavigationBar, FloatingActionButton, Drawer는 다른 글에서 상세히 다루겠습니다.

 

 

https://jinhan38.tistory.com/126

 

[Flutter] AppBar 사용법

이번 포스팅에서는 AppBar의 사용법을 알아보겠습니다. AppBar는 대부분 Scaffold위젯과 함께 사용됩니다. 새로운 페이지로 이동할 때 뒤로가기 버튼과 페이지 이름, 필요하다면 추가적인 버튼들을

jinhan38.com

 

 

 

 

1. primary

2. extendBodyBehindAppBar

3. resizeToAvoidBottomInset

4. persistentFooterButtons

 

 

 

 

 

1. primary

 

Scaffold의 primary 특성은 AppBar와 함께 사용할 때 동작합니다. primary가 true라면 앱바의 높이에 디바이스의 상태바 높이가 추가됩니다. 만약 false일 경우 앱바 자체의 높이만큼만 그려집니다. AppBar에도 primary 특성이 있는데 이것은 앱바가 상태바의 영역까지 확장할 것인가 아닌가에 대한 설정입니다. 그래서 두 개의 primary를 모두 false로 한다면 오른쪽 이미지처럼 앱바의 크기가 작아지고 상태바의 영역까지 앱바가 올라갑니다.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        primary: false,
        title: const Text("ScaffoldScreen"),
      ),
      backgroundColor: Colors.grey.shade400,
      primary: false,
      extendBodyBehindAppBar: true,
      body: const Text(
        "Scaffold Widget",
        style: TextStyle(fontSize: 30),
      ),
    );
  }

 

 

 

 

2. extendBodyBehindAppBar

extendBodyBehindAppBar 특성은 Scaffold의 body에 들어갈 위젯이 앱바의 영역까지 사용할 수 있는지 없는지의 여부를 설정합니다. true인 경우 앱바의 영역까지 사용할 수 있으며, false인 경우 앱바의 영역을 사용할 수 없습니다. 기본값은 false입니다. 

오른쪽 이미지는 true로 설정했기 때문에 height가 100인 빨간 컨태이너가 앱바 뒤의 영역까지 사용하고 있습니다. 

영역 구분을 위해서 앱바의 배경색과 내부 컨텐츠들의 색을 변경했습니다. 앱바에 대한 자세한 정보는 상단에 첨부한 링크를 확인해 주시기 바랍니다.

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        primary: false,
        elevation: 0,
        title: const Text(
          "ScaffoldScreen",
          style: TextStyle(color: Colors.black),
        ),
        backgroundColor: Colors.white.withOpacity(0.3),
        foregroundColor: Colors.black,
      ),
      backgroundColor: Colors.grey.shade400,
      primary: false,
      extendBodyBehindAppBar: true,
      body: Container(
        height: 100,
        color: Colors.red,
      ),
    );
  }

 

 

 

3. resizeToAvoidBottomInset

resizeToAvoidBottomInset 특성은 키보드가 올라 왔을 때 body의 위젯 사이즈를 resize 할지 말지 결정합니다. true인 경우 resize 하고, false인 경우 body 위젯은 그대로인 상태로 키보드만 올라옵니다. 기본 값은 true입니다.

키보드를 올리기 위해 화면 하단부에 TextFormField 위젯과 빨간 컨태이너를 추가했습니다. 만약 body 위젯의 길이가 길다면 스크롤이 있는 위젯을 추가해서 사용하면 좋습니다.

 

왼쪽 이미지 true, 오른쪽 이미지 false

 

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        primary: false,
        elevation: 0,
        title: const Text(
          "ScaffoldScreen",
          style: TextStyle(color: Colors.black),
        ),
        backgroundColor: Colors.white.withOpacity(0.3),
        foregroundColor: Colors.black,
      ),
      backgroundColor: Colors.grey.shade400,
      primary: false,
      extendBodyBehindAppBar: true,
      
      // 이부분 수정 
      resizeToAvoidBottomInset: false,
      
      body: Column(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Padding(
            padding: const EdgeInsets.all(20.0),
            child: TextFormField(
              decoration: const InputDecoration(
                hintText: "아이디를 입력하세요",
                hintStyle: TextStyle(color: Colors.white),
              ),
            ),
          ),
          Container(
            height: 100,
            color: Colors.red,
          ),
        ],
      ),
    );
  }

 

 

 

4. persistentFooterButtons

persistentFooterButtons 특성은 화면 하단에 특정 위젯들을 고정시키는 기능입니다. persistentFooterButtons에 사용한 위젯들은 키보드가 올라오더라도 resize되지 않습니다. 

persistentFooterButtons과 관련된 특성은 persistentFooterAlignment와 extendBody가 있습니다. persistentFooterAlignment는 위젯들을 어떻게 배치시킬지 AlignmentDirectional 클래스를 사용해서 설정할 수 있습니다. extendBody는 Scaffold.body 위젯이 persistentFooterButtons의 영역까지 확장할지 말지를 결정합니다. true로 주면 확장되고, false로 설정하면 넘어오지 않습니다. 

그리고 persistentFooterButtons을 사용하면 위쪽에 Divider가 하나 생깁니다. Theme위젯의 dividerColor에 transparent를 입력해서 없앨 수 있습니다. 

 

왼쪽 extendBody = true, 오른쪽 extendBody = false

 

 

 

 

Full code

import 'package:flutter/material.dart';

class ScaffoldScreen extends StatefulWidget {
  const ScaffoldScreen({Key? key}) : super(key: key);

  @override
  State<ScaffoldScreen> createState() => _ScaffoldScreenState();
}

class _ScaffoldScreenState extends State<ScaffoldScreen> {
  @override
  Widget build(BuildContext context) {
    // persistentFooterButtons 의 상단 divider 컬러 변경
    return Theme(
      data: ThemeData().copyWith(
        dividerColor: Colors.transparent,
      ),
      child: Scaffold(
        appBar: AppBar(
          primary: false,
          elevation: 0,
          title: const Text(
            "ScaffoldScreen",
            style: TextStyle(color: Colors.black),
          ),
          backgroundColor: Colors.white.withOpacity(0.3),
          foregroundColor: Colors.black,
        ),
        backgroundColor: Colors.grey.shade400,
        primary: false,
        extendBodyBehindAppBar: true,
        resizeToAvoidBottomInset: true,
        persistentFooterAlignment: AlignmentDirectional.center,
        extendBody: false,
        persistentFooterButtons: [
          Container(
            padding: EdgeInsets.zero,
            width: 150,
            height: 50,
            color: Colors.white,
            alignment: Alignment.center,
            child: const Text(
              "Button",
              style: TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
            ),
          ),
        ],
        body: ListView(
          padding: EdgeInsets.zero,
          children: [
            const SizedBox(height: 100),
            Padding(
              padding: const EdgeInsets.all(20.0),
              child: TextFormField(
                decoration: const InputDecoration(
                  hintText: "아이디를 입력하세요",
                  hintStyle: TextStyle(color: Colors.white),
                ),
              ),
            ),
            Container(
              height: 150,
              color: Colors.red,
            ),
            Container(
              height: 150,
              color: Colors.orange,
            ),
            Container(
              height: 150,
              color: Colors.yellow,
            ),
            Container(
              height: 150,
              color: Colors.green,
            ),
            Container(
              height: 150,
              color: Colors.blue,
            ),
            Container(
              height: 150,
              color: Colors.indigo,
            ),
          ],
        ),
      ),
    );
  }
}