[Flutter 基础] - Scaffold 的基本用法介绍

859 阅读3分钟

在 Flutter 中,Scaffold 是构建 Material Design 风格页面的核心组件,它提供了基础的页面结构框架,可以快速集成常见的 UI 元素(如 AppBar、抽屉菜单、悬浮按钮等)。以下是 Scaffold 的详细用法和常见配置:


一、Scaffold 的基本结构

Scaffold(
  appBar: AppBar(...),
  body: Container(...),
  floatingActionButton: FloatingActionButton(...),
  drawer: Drawer(...),
  bottomNavigationBar: BottomNavigationBar(...),
  // 其他参数...
);

二、核心属性和用法

1. appBar(顶部导航栏)

  • 类型:AppBar
  • 用途:显示标题、导航按钮、操作菜单等。
  • 常用配置:
    appBar: AppBar(
      title: Text('首页'),
      leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
      actions: [
        IconButton(icon: Icon(Icons.search), onPressed: () {}),
      ],
      backgroundColor: Colors.blue,
    ),
    

2. body(页面主体内容)

  • 类型:Widget
  • 用途:页面的主要内容区域。
  • 示例:
    body: Center(
      child: Text('Hello Flutter!'),
    ),
    

3. floatingActionButton(悬浮按钮)

  • 类型:FloatingActionButton
  • 用途:显示一个悬浮的圆形操作按钮。
  • 位置调整:
    floatingActionButton: FloatingActionButton(
      onPressed: () {},
      child: Icon(Icons.add),
    ),
    floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, // 位置配置
    

4. drawer(左侧抽屉菜单)

  • 类型:Drawer
  • 用途:从左侧滑出的导航菜单。
  • 示例:
    drawer: Drawer(
      child: ListView(
        children: [
          DrawerHeader(child: Text('Header')),
          ListTile(title: Text('Item 1')),
          ListTile(title: Text('Item 2')),
        ],
      ),
    ),
    

5. endDrawer(右侧抽屉菜单)

  • 类型:Drawer
  • 用法与 drawer 类似,但从右侧滑出。

6. bottomNavigationBar(底部导航栏)

  • 类型:BottomNavigationBar
  • 用途:底部导航栏,支持多个标签切换。
  • 示例:
    bottomNavigationBar: BottomNavigationBar(
      items: [
        BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
        BottomNavigationBarItem(icon: Icon(Icons.settings), label: '设置'),
      ],
      currentIndex: _selectedIndex,
      onTap: (index) => setState(() => _selectedIndex = index),
    ),
    

7. backgroundColor(背景颜色)

  • 类型:Color
  • 用途:设置整个 Scaffold 的背景颜色。
  • 示例:
    backgroundColor: Colors.grey[200],
    

8. resizeToAvoidBottomInset(避免键盘遮挡)

  • 类型:bool
  • 用途:当键盘弹出时是否自动调整布局(默认 true)。

三、高级用法

1. 嵌套 Scaffold

  • 可以在页面中嵌套多个 Scaffold,但需要注意上下文(如 ScaffoldMessenger 用于显示 SnackBar):
    Scaffold(
      body: Scaffold(
        appBar: AppBar(title: Text('嵌套 Scaffold')),
      ),
    );
    

2. 自定义底部栏

  • 通过 bottomSheet 属性实现自定义底部栏:

image.png

  bottomSheet: Container(
    height: 50,
    color: Colors.blue,
    child: Center(child: Text('Custom Bottom Sheet')),
  ),

bottomSheet一般和bottomNavigationBar不会同时出现,当bottomNavigationBar不能满足业务需求的时候,可以考虑使用bootomSheet来自定义一个底部栏。当然,两个同时出现也不会有什么问题。少部分场景可能需要二级导航栏的时候,也是可以用的。

3. 控制抽屉菜单

  • 手动打开/关闭抽屉:
    // 打开左侧抽屉
    Scaffold.of(context).openDrawer();
    // 打开右侧抽屉
    Scaffold.of(context).openEndDrawer();
    

四、完整示例代码

import 'package:flutter/material.dart';

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scaffold 示例'),
        actions: [IconButton(icon: Icon(Icons.share), onPressed: () {})],
      ),
      drawer: Drawer(
        child: ListView(
          children: [
              GestureDetector(
                  onTap: (){
                    scaffoldKey.currentState?.closeDrawer(); //关闭左侧菜单栏
                  },
                  child: ListTile(title: Text('菜单项1')),
             ),
            GestureDetector(
              onTap: (){
                scaffoldKey.currentState?.closeDrawer(); //关闭左侧菜单栏
              },
              child: ListTile(title: Text('菜单项2')),
            ),
          ],
        ),
      ),
      body: Center(
        child: Text('当前页面: $_selectedIndex'),
      ),
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
          BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.amber[800],
        onTap: (index) => setState(() => _selectedIndex = index),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {},
        child: Icon(Icons.add),
      ),
    );
  }
}

五、注意事项

  1. 避免过度嵌套:Scaffold 通常作为页面的根组件,避免多层嵌套导致性能问题。
  2. 上下文问题:在 Scaffold 的子组件中调用 Scaffold.of(context) 时,确保 context 正确。
  3. 键盘处理:当页面有输入框时,resizeToAvoidBottomInset 会自动调整布局防止键盘遮挡。

通过灵活组合 Scaffold 的各个属性,可以快速构建出符合 Material Design 规范的复杂页面结构。