Flutter Scaffold 组件总结

65 阅读12分钟

Flutter Scaffold 组件总结

概述

Scaffold 是 Flutter 中实现 Material Design 布局的基础组件,提供了应用程序页面的基本视觉结构和布局框架。它作为一个容器,组合了多个常用的UI元素,如应用栏(AppBar)、主内容区域(body)、悬浮操作按钮(FloatingActionButton)、抽屉(Drawer)等,确保应用程序界面符合 Material Design 规范。

原理说明

1. 设计理念

Scaffold 基于 Material Design 的设计原则,提供了一个标准化的页面布局结构:

  • 层次化布局:通过组合不同的子组件,形成清晰的视觉层次
  • 一致性:确保应用程序在不同页面间保持一致的布局和交互模式
  • 可扩展性:支持灵活的组件组合,满足不同场景的需求

2. 布局管理

Scaffold 内部使用 CustomMultiChildLayout 来管理各个子组件的位置和大小:

  • AppBar 固定在页面顶部
  • Body 占据主要内容区域
  • FloatingActionButton 悬浮在指定位置
  • Drawer 从侧边滑出
  • BottomNavigationBar 固定在页面底部

3. 状态管理

Scaffold 维护一个 ScaffoldState 对象,管理:

  • 抽屉的开关状态
  • SnackBar 的显示和隐藏
  • 底部表单的显示
  • 悬浮操作按钮的动画

构造函数

Scaffold({
  Key? key,                                    // 组件的唯一标识符
  PreferredSizeWidget? appBar,                 // 页面顶部的应用栏,通常是AppBar
  Widget? body,                                // 页面的主要内容区域
  Widget? floatingActionButton,                // 悬浮操作按钮,通常用于主要操作
  FloatingActionButtonLocation? floatingActionButtonLocation, // 悬浮按钮的位置
  FloatingActionButtonAnimator? floatingActionButtonAnimator, // 悬浮按钮的动画器
  List<Widget>? persistentFooterButtons,       // 持久化底部按钮列表
  Widget? drawer,                              // 左侧抽屉菜单
  DrawerCallback? onDrawerChanged,             // 抽屉状态改变时的回调函数
  Widget? endDrawer,                           // 右侧抽屉菜单
  DrawerCallback? onEndDrawerChanged,          // 右侧抽屉状态改变时的回调函数
  Widget? bottomNavigationBar,                 // 底部导航栏
  Widget? bottomSheet,                         // 底部表单,从底部向上滑出
  Color? backgroundColor,                      // Scaffold的背景颜色
  bool? resizeToAvoidBottomInset,             // 是否调整大小以避免底部插入(如键盘)
  bool primary = true,                         // 是否为主要的Scaffold,影响状态栏处理
  DragStartBehavior dragStartBehavior = DragStartBehavior.start, // 拖拽开始行为
  bool extendBody = false,                     // 是否将body扩展到底部导航栏下方
  bool extendBodyBehindAppBar = false,         // 是否将body扩展到AppBar后面
  Color? drawerScrimColor,                     // 抽屉遮罩层颜色
  double? drawerEdgeDragWidth,                 // 抽屉边缘拖拽区域宽度
  bool drawerEnableOpenDragGesture = true,     // 是否启用拖拽手势打开左侧抽屉
  bool endDrawerEnableOpenDragGesture = true,  // 是否启用拖拽手势打开右侧抽屉
  String? restorationId,                       // 状态恢复标识符
})

主要属性

核心属性

属性名类型说明
appBarPreferredSizeWidget?页面顶部的应用栏
bodyWidget?页面的主要内容区域
floatingActionButtonWidget?悬浮操作按钮
drawerWidget?左侧抽屉菜单
endDrawerWidget?右侧抽屉菜单
bottomNavigationBarWidget?底部导航栏
bottomSheetWidget?底部表单

配置属性

属性名类型默认值说明
floatingActionButtonLocationFloatingActionButtonLocation?FloatingActionButtonLocation.endFloat悬浮按钮位置
floatingActionButtonAnimatorFloatingActionButtonAnimator?FloatingActionButtonAnimator.scaling悬浮按钮动画器
persistentFooterButtonsList<Widget>?null持久化底部按钮
resizeToAvoidBottomInsetbool?true是否调整大小以避免底部插入
primarybooltrue是否为主要Scaffold
extendBodyboolfalse是否扩展body到底部
extendBodyBehindAppBarboolfalse是否扩展body到AppBar后面

实现方式

1. 基础用法

import 'package:flutter/material.dart';

class BasicScaffoldExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('基础示例'),
        backgroundColor: Colors.blue,
      ),
      body: Center(
        child: Text(
          'Hello Flutter!',
          style: TextStyle(fontSize: 24),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          print('悬浮按钮被点击');
        },
        child: Icon(Icons.add),
        tooltip: '添加',
      ),
    );
  }
}

2. 完整功能示例

import 'package:flutter/material.dart';

class FullFeaturedScaffoldExample extends StatefulWidget {
  @override
  _FullFeaturedScaffoldExampleState createState() => _FullFeaturedScaffoldExampleState();
}

class _FullFeaturedScaffoldExampleState extends State<FullFeaturedScaffoldExample> {
  int _selectedIndex = 0;
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  void _showSnackBar() {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('这是一个SnackBar'),
        action: SnackBarAction(
          label: '撤销',
          onPressed: () {
            // 撤销操作
          },
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text('完整功能示例'),
        backgroundColor: Colors.deepPurple,
        actions: [
          IconButton(
            icon: Icon(Icons.search),
            onPressed: () {
              // 搜索功能
            },
          ),
          IconButton(
            icon: Icon(Icons.more_vert),
            onPressed: () {
              // 更多选项
            },
          ),
        ],
      ),
      body: IndexedStack(
        index: _selectedIndex,
        children: [
          _buildHomePage(),
          _buildBusinessPage(),
          _buildProfilePage(),
        ],
      ),
      drawer: Drawer(
        child: ListView(
          padding: EdgeInsets.zero,
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                color: Colors.deepPurple,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  CircleAvatar(
                    radius: 30,
                    backgroundColor: Colors.white,
                    child: Icon(Icons.person, size: 40, color: Colors.deepPurple),
                  ),
                  SizedBox(height: 10),
                  Text(
                    '用户名',
                    style: TextStyle(color: Colors.white, fontSize: 18),
                  ),
                  Text(
                    'user@example.com',
                    style: TextStyle(color: Colors.white70, fontSize: 14),
                  ),
                ],
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('首页'),
              onTap: () {
                Navigator.pop(context);
                setState(() {
                  _selectedIndex = 0;
                });
              },
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('设置'),
              onTap: () {
                Navigator.pop(context);
                // 导航到设置页面
              },
            ),
            ListTile(
              leading: Icon(Icons.help),
              title: Text('帮助'),
              onTap: () {
                Navigator.pop(context);
                // 显示帮助信息
              },
            ),
            Divider(),
            ListTile(
              leading: Icon(Icons.logout),
              title: Text('退出登录'),
              onTap: () {
                Navigator.pop(context);
                // 执行退出登录
              },
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _showSnackBar,
        child: Icon(Icons.message),
        tooltip: '显示消息',
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '首页',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            label: '业务',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '个人',
          ),
        ],
        currentIndex: _selectedIndex,
        selectedItemColor: Colors.deepPurple,
        onTap: _onItemTapped,
      ),
      persistentFooterButtons: [
        TextButton(
          onPressed: () {
            // 持久化按钮1
          },
          child: Text('按钮1'),
        ),
        TextButton(
          onPressed: () {
            // 持久化按钮2
          },
          child: Text('按钮2'),
        ),
      ],
    );
  }

  Widget _buildHomePage() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.home, size: 80, color: Colors.deepPurple),
          SizedBox(height: 20),
          Text('首页', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }

  Widget _buildBusinessPage() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.business, size: 80, color: Colors.deepOrange),
          SizedBox(height: 20),
          Text('业务', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }

  Widget _buildProfilePage() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(Icons.person, size: 80, color: Colors.green),
          SizedBox(height: 20),
          Text('个人', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
        ],
      ),
    );
  }
}

3. 高级用法 - 自定义Scaffold状态

import 'package:flutter/material.dart';

class CustomScaffoldExample extends StatefulWidget {
  @override
  _CustomScaffoldExampleState createState() => _CustomScaffoldExampleState();
}

class _CustomScaffoldExampleState extends State<CustomScaffoldExample> {
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  bool _isDrawerOpen = false;

  void _toggleDrawer() {
    if (_isDrawerOpen) {
      Navigator.of(context).pop();
    } else {
      _scaffoldKey.currentState?.openDrawer();
    }
    setState(() {
      _isDrawerOpen = !_isDrawerOpen;
    });
  }

  void _showBottomSheet() {
    showModalBottomSheet(
      context: context,
      builder: (BuildContext context) {
        return Container(
          height: 200,
          child: Column(
            children: [
              ListTile(
                leading: Icon(Icons.share),
                title: Text('分享'),
                onTap: () {
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.link),
                title: Text('复制链接'),
                onTap: () {
                  Navigator.pop(context);
                },
              ),
              ListTile(
                leading: Icon(Icons.edit),
                title: Text('编辑'),
                onTap: () {
                  Navigator.pop(context);
                },
              ),
            ],
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      appBar: AppBar(
        title: Text('自定义Scaffold'),
        leading: IconButton(
          icon: Icon(_isDrawerOpen ? Icons.close : Icons.menu),
          onPressed: _toggleDrawer,
        ),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            Card(
              child: ListTile(
                title: Text('显示SnackBar'),
                trailing: Icon(Icons.arrow_forward_ios),
                onTap: () {
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text('这是一个自定义SnackBar'),
                      duration: Duration(seconds: 2),
                    ),
                  );
                },
              ),
            ),
            Card(
              child: ListTile(
                title: Text('显示底部表单'),
                trailing: Icon(Icons.arrow_forward_ios),
                onTap: _showBottomSheet,
              ),
            ),
            Card(
              child: ListTile(
                title: Text('显示对话框'),
                trailing: Icon(Icons.arrow_forward_ios),
                onTap: () {
                  showDialog(
                    context: context,
                    builder: (BuildContext context) {
                      return AlertDialog(
                        title: Text('确认'),
                        content: Text('你确定要执行这个操作吗?'),
                        actions: [
                          TextButton(
                            child: Text('取消'),
                            onPressed: () {
                              Navigator.of(context).pop();
                            },
                          ),
                          TextButton(
                            child: Text('确定'),
                            onPressed: () {
                              Navigator.of(context).pop();
                              ScaffoldMessenger.of(context).showSnackBar(
                                SnackBar(content: Text('操作已执行')),
                              );
                            },
                          ),
                        ],
                      );
                    },
                  );
                },
              ),
            ),
          ],
        ),
      ),
      drawer: Drawer(
        child: ListView(
          children: [
            DrawerHeader(
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  colors: [Colors.blue, Colors.purple],
                ),
              ),
              child: Text(
                '导航菜单',
                style: TextStyle(color: Colors.white, fontSize: 24),
              ),
            ),
            ListTile(
              leading: Icon(Icons.home),
              title: Text('首页'),
              onTap: () {
                Navigator.pop(context);
              },
            ),
            ListTile(
              leading: Icon(Icons.settings),
              title: Text('设置'),
              onTap: () {
                Navigator.pop(context);
              },
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton.extended(
        onPressed: () {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('扩展悬浮按钮被点击')),
          );
        },
        label: Text('操作'),
        icon: Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      resizeToAvoidBottomInset: true,
      extendBody: true,
    );
  }
}

Scaffold状态管理

1. ScaffoldState 访问

// 方式1:使用GlobalKey
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

Scaffold(
  key: _scaffoldKey,
  // ...
);

// 访问状态
_scaffoldKey.currentState?.openDrawer();

// 方式2:使用Scaffold.of(context)(在子组件中)
Scaffold.of(context).openDrawer();

// 方式3:使用Builder确保正确的context
Builder(
  builder: (BuildContext context) {
    return ElevatedButton(
      onPressed: () {
        Scaffold.of(context).openDrawer();
      },
      child: Text('打开抽屉'),
    );
  },
);

2. ScaffoldMessenger

// 显示SnackBar
ScaffoldMessenger.of(context).showSnackBar(
  SnackBar(
    content: Text('消息内容'),
    action: SnackBarAction(
      label: '撤销',
      onPressed: () {
        // 撤销操作
      },
    ),
  ),
);

// 隐藏当前SnackBar
ScaffoldMessenger.of(context).hideCurrentSnackBar();

// 移除所有SnackBar
ScaffoldMessenger.of(context).removeCurrentSnackBar();

常见配置选项

1. FloatingActionButton位置

// 预定义位置
FloatingActionButtonLocation.startTop          // 左上角
FloatingActionButtonLocation.centerTop         // 顶部中央
FloatingActionButtonLocation.endTop            // 右上角
FloatingActionButtonLocation.startFloat        // 左侧悬浮
FloatingActionButtonLocation.centerFloat       // 中央悬浮
FloatingActionButtonLocation.endFloat          // 右侧悬浮(默认)
FloatingActionButtonLocation.startDocked       // 左侧停靠
FloatingActionButtonLocation.centerDocked      // 中央停靠
FloatingActionButtonLocation.endDocked         // 右侧停靠

// 自定义位置
class CustomFabLocation extends FloatingActionButtonLocation {
  @override
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    // 返回自定义位置
    return Offset(100.0, 100.0);
  }
}

2. 响应式布局

Scaffold(
  appBar: AppBar(title: Text('响应式示例')),
  body: LayoutBuilder(
    builder: (context, constraints) {
      if (constraints.maxWidth > 600) {
        // 宽屏布局
        return Row(
          children: [
            Expanded(flex: 1, child: _buildSidebar()),
            Expanded(flex: 3, child: _buildMainContent()),
          ],
        );
      } else {
        // 窄屏布局
        return _buildMainContent();
      }
    },
  ),
  drawer: MediaQuery.of(context).size.width <= 600 ? _buildDrawer() : null,
);

注意事项和最佳实践

1. 性能优化

// 使用const构造函数
const Scaffold(
  appBar: const CustomAppBar(),
  body: const MainContent(),
);

// 避免在build方法中创建复杂对象
class OptimizedScaffold extends StatelessWidget {
  static const _appBar = AppBar(title: Text('优化示例'));
  static const _fab = FloatingActionButton(
    onPressed: null,
    child: Icon(Icons.add),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: _appBar,
      body: MainContent(),
      floatingActionButton: _fab,
    );
  }
}

2. 错误处理

class SafeScaffoldExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('安全示例')),
      body: Builder(
        builder: (BuildContext context) {
          return Center(
            child: ElevatedButton(
              onPressed: () {
                try {
                  // 确保context是Scaffold的子级
                  Scaffold.of(context).openDrawer();
                } catch (e) {
                  // 处理错误
                  print('无法打开抽屉: $e');
                }
              },
              child: Text('打开抽屉'),
            ),
          );
        },
      ),
      drawer: Drawer(
        child: ListView(
          children: [
            DrawerHeader(child: Text('抽屉')),
            ListTile(title: Text('选项1')),
          ],
        ),
      ),
    );
  }
}

3. 主题和样式

class ThemedScaffoldExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Theme(
      data: Theme.of(context).copyWith(
        scaffoldBackgroundColor: Colors.grey[100],
        appBarTheme: AppBarTheme(
          backgroundColor: Colors.deepPurple,
          foregroundColor: Colors.white,
          elevation: 4,
        ),
        floatingActionButtonTheme: FloatingActionButtonThemeData(
          backgroundColor: Colors.deepPurple,
          foregroundColor: Colors.white,
        ),
      ),
      child: Scaffold(
        appBar: AppBar(title: Text('主题示例')),
        body: Center(child: Text('自定义主题的Scaffold')),
        floatingActionButton: FloatingActionButton(
          onPressed: () {},
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

高级属性详解

1. bottomSheet - 底部表单

bottomSheet 属性用于在页面底部显示一个持久的表单面板。

基本用法
import 'package:flutter/material.dart';

class BottomSheetExample extends StatefulWidget {
  @override
  _BottomSheetExampleState createState() => _BottomSheetExampleState();
}

class _BottomSheetExampleState extends State<BottomSheetExample> {
  bool _showBottomSheet = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('bottomSheet 示例'),
        backgroundColor: Colors.blue,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '注意:当显示底部表单时,',
              style: TextStyle(fontSize: 16),
            ),
            Text(
              '这个内容区域会被向上压缩',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                setState(() {
                  _showBottomSheet = !_showBottomSheet;
                });
              },
              child: Text(_showBottomSheet ? '隐藏底部表单' : '显示底部表单'),
            ),
          ],
        ),
      ),
      bottomSheet: _showBottomSheet
          ? Container(
              height: 150,
              width: double.infinity,
              decoration: BoxDecoration(
                color: Colors.blue[50],
                borderRadius: BorderRadius.only(
                  topLeft: Radius.circular(20),
                  topRight: Radius.circular(20),
                ),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black26,
                    blurRadius: 10,
                    offset: Offset(0, -2),
                  ),
                ],
              ),
              child: Column(
                children: [
                  Container(
                    width: 50,
                    height: 5,
                    margin: EdgeInsets.symmetric(vertical: 10),
                    decoration: BoxDecoration(
                      color: Colors.grey[400],
                      borderRadius: BorderRadius.circular(3),
                    ),
                  ),
                  Text(
                    '这是一个持久的底部表单',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  SizedBox(height: 10),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                    children: [
                      ElevatedButton.icon(
                        onPressed: () {},
                        icon: Icon(Icons.share),
                        label: Text('分享'),
                      ),
                      ElevatedButton.icon(
                        onPressed: () {},
                        icon: Icon(Icons.download),
                        label: Text('下载'),
                      ),
                      ElevatedButton.icon(
                        onPressed: () {},
                        icon: Icon(Icons.favorite),
                        label: Text('收藏'),
                      ),
                    ],
                  ),
                ],
              ),
            )
          : null,
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 显示模态底部表单作为对比
          showModalBottomSheet(
            context: context,
            builder: (context) => Container(
              height: 200,
              child: Center(
                child: Text(
                  '这是模态底部表单\n(与 bottomSheet 不同)',
                  textAlign: TextAlign.center,
                  style: TextStyle(fontSize: 18),
                ),
              ),
            ),
          );
        },
        child: Icon(Icons.help),
        tooltip: '显示模态底部表单对比',
      ),
    );
  }
}

2. floatingActionButtonAnimator - 悬浮按钮动画器

控制 FAB 位置变化时的动画效果。

import 'package:flutter/material.dart';

class FABAnimatorExample extends StatefulWidget {
  @override
  _FABAnimatorExampleState createState() => _FABAnimatorExampleState();
}

class _FABAnimatorExampleState extends State<FABAnimatorExample> {
  FloatingActionButtonLocation _fabLocation = FloatingActionButtonLocation.endFloat;
  FloatingActionButtonAnimator _fabAnimator = FloatingActionButtonAnimator.scaling;
  
  final List<FloatingActionButtonLocation> _locations = [
    FloatingActionButtonLocation.startFloat,
    FloatingActionButtonLocation.centerFloat,
    FloatingActionButtonLocation.endFloat,
    FloatingActionButtonLocation.startDocked,
    FloatingActionButtonLocation.centerDocked,
    FloatingActionButtonLocation.endDocked,
  ];
  
  final Map<FloatingActionButtonAnimator, String> _animators = {
    FloatingActionButtonAnimator.scaling: '缩放动画',
    FloatingActionButtonAnimator.noAnimation: '无动画',
  };

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FAB 动画器示例'),
        backgroundColor: Colors.purple,
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              '动画器类型:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            ..._animators.entries.map((entry) => RadioListTile<FloatingActionButtonAnimator>(
              title: Text(entry.value),
              value: entry.key,
              groupValue: _fabAnimator,
              onChanged: (value) {
                setState(() {
                  _fabAnimator = value!;
                });
              },
            )),
            SizedBox(height: 20),
            Text(
              'FAB 位置:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            Expanded(
              child: GridView.count(
                crossAxisCount: 2,
                childAspectRatio: 3,
                children: _locations.map((location) {
                  String locationName = location.toString().split('.').last;
                  return Padding(
                    padding: EdgeInsets.all(4.0),
                    child: ElevatedButton(
                      onPressed: () {
                        setState(() {
                          _fabLocation = location;
                        });
                      },
                      style: ElevatedButton.styleFrom(
                        backgroundColor: _fabLocation == location ? Colors.purple : null,
                      ),
                      child: Text(
                        locationName,
                        style: TextStyle(fontSize: 12),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  );
                }).toList(),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('FAB 被点击了!')),
          );
        },
        child: Icon(Icons.play_arrow),
        backgroundColor: Colors.purple,
      ),
      floatingActionButtonLocation: _fabLocation,
      floatingActionButtonAnimator: _fabAnimator,
      bottomNavigationBar: BottomNavigationBar(
        items: [
          BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'),
          BottomNavigationBarItem(icon: Icon(Icons.settings), label: '设置'),
        ],
      ),
    );
  }
}

3. persistentFooterButtons - 持久化底部按钮

在页面底部显示持久的操作按钮。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(title: 'SafeArea 示例', home: FABAnimatorExample());
  }
}

class PersistentFooterButtonsExample extends StatefulWidget {
  @override
  _PersistentFooterButtonsExampleState createState() => _PersistentFooterButtonsExampleState();
}

class _PersistentFooterButtonsExampleState extends State<PersistentFooterButtonsExample> {
  bool _showFooterButtons = true;
  String _selectedAction = '';

  void _performAction(String action) {
    setState(() {
      _selectedAction = action;
    });
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text('执行了: $action'),
        duration: Duration(seconds: 1),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('持久化底部按钮示例'),
        backgroundColor: Colors.green,
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SwitchListTile(
              title: Text('显示持久化底部按钮'),
              value: _showFooterButtons,
              onChanged: (value) {
                setState(() {
                  _showFooterButtons = value;
                });
              },
            ),
            SizedBox(height: 20),
            Text(
              '模拟表单内容:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            SizedBox(height: 10),
            TextField(
              decoration: InputDecoration(
                labelText: '用户名',
                border: OutlineInputBorder(),
              ),
            ),
            SizedBox(height: 10),
            TextField(
              decoration: InputDecoration(
                labelText: '邮箱',
                border: OutlineInputBorder(),
              ),
            ),
            SizedBox(height: 10),
            TextField(
              decoration: InputDecoration(
                labelText: '电话',
                border: OutlineInputBorder(),
              ),
              keyboardType: TextInputType.phone,
            ),
            SizedBox(height: 20),
            if (_selectedAction.isNotEmpty)
              Container(
                padding: EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Colors.green[50],
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(color: Colors.green),
                ),
                child: Text(
                  '最后执行的操作: $_selectedAction',
                  style: TextStyle(
                    color: Colors.green[800],
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ),
          ],
        ),
      ),
      persistentFooterButtons: _showFooterButtons
          ? [
              TextButton.icon(
                onPressed: () => _performAction('取消'),
                icon: Icon(Icons.cancel, color: Colors.red),
                label: Text(
                  '取消',
                  style: TextStyle(color: Colors.red),
                ),
              ),
              TextButton.icon(
                onPressed: () => _performAction('保存草稿'),
                icon: Icon(Icons.save, color: Colors.orange),
                label: Text(
                  '保存草稿',
                  style: TextStyle(color: Colors.orange),
                ),
              ),
              ElevatedButton.icon(
                onPressed: () => _performAction('提交'),
                icon: Icon(Icons.send),
                label: Text('提交'),
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.green,
                ),
              ),
            ]
          : null,
    );
  }
}

4. resizeToAvoidBottomInset - 避免底部插入调整

控制当软键盘弹出时页面的调整行为。

import 'package:flutter/material.dart';

class ResizeToAvoidBottomInsetExample extends StatefulWidget {
  @override
  _ResizeToAvoidBottomInsetExampleState createState() => _ResizeToAvoidBottomInsetExampleState();
}

class _ResizeToAvoidBottomInsetExampleState extends State<ResizeToAvoidBottomInsetExample> {
  bool? _resizeToAvoidBottomInset = true;
  final TextEditingController _controller = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('键盘避让示例'),
        backgroundColor: Colors.orange,
      ),
      resizeToAvoidBottomInset: _resizeToAvoidBottomInset,
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          children: [
            Card(
              color: Colors.orange[50],
              child: Padding(
                padding: EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'resizeToAvoidBottomInset 设置:',
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    RadioListTile<bool?>(
                      title: Text('true - 页面调整避开键盘'),
                      value: true,
                      groupValue: _resizeToAvoidBottomInset,
                      onChanged: (value) {
                        setState(() {
                          _resizeToAvoidBottomInset = value;
                        });
                      },
                    ),
                    RadioListTile<bool?>(
                      title: Text('false - 页面不调整,键盘可能遮挡'),
                      value: false,
                      groupValue: _resizeToAvoidBottomInset,
                      onChanged: (value) {
                        setState(() {
                          _resizeToAvoidBottomInset = value;
                        });
                      },
                    ),
                    RadioListTile<bool?>(
                      title: Text('null - 使用系统默认行为'),
                      value: null,
                      groupValue: _resizeToAvoidBottomInset,
                      onChanged: (value) {
                        setState(() {
                          _resizeToAvoidBottomInset = value;
                        });
                      },
                    ),
                  ],
                ),
              ),
            ),
            SizedBox(height: 20),
            Text(
              '请点击下方输入框测试效果:',
              style: TextStyle(fontSize: 16),
            ),
            Spacer(),
            // 底部的输入框,用于测试键盘弹出效果
            Container(
              padding: EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black12,
                    blurRadius: 10,
                    offset: Offset(0, 2),
                  ),
                ],
              ),
              child: Column(
                children: [
                  TextField(
                    controller: _controller,
                    decoration: InputDecoration(
                      labelText: '在这里输入文字',
                      hintText: '点击这里会弹出键盘',
                      border: OutlineInputBorder(),
                      prefixIcon: Icon(Icons.edit),
                    ),
                    maxLines: 3,
                  ),
                  SizedBox(height: 10),
                  Row(
                    children: [
                      Expanded(
                        child: ElevatedButton(
                          onPressed: () {
                            _controller.clear();
                            FocusScope.of(context).unfocus();
                          },
                          child: Text('清空'),
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.grey,
                          ),
                        ),
                      ),
                      SizedBox(width: 10),
                      Expanded(
                        child: ElevatedButton(
                          onPressed: () {
                            if (_controller.text.isNotEmpty) {
                              ScaffoldMessenger.of(context).showSnackBar(
                                SnackBar(
                                  content: Text('输入内容: ${_controller.text}'),
                                ),
                              );
                            }
                          },
                          child: Text('提交'),
                          style: ElevatedButton.styleFrom(
                            backgroundColor: Colors.orange,
                          ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
            SizedBox(height: 20),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

5. primary - 是否为主要 Scaffold

控制 Scaffold 是否是当前路由的主要 Scaffold,影响状态栏处理。

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class PrimaryScaffoldExample extends StatefulWidget {
  @override
  _PrimaryScaffoldExampleState createState() => _PrimaryScaffoldExampleState();
}

class _PrimaryScaffoldExampleState extends State<PrimaryScaffoldExample> {
  bool _primary = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      primary: _primary,
      appBar: AppBar(
        title: Text('primary 属性示例'),
        backgroundColor: Colors.indigo,
        systemOverlayStyle: SystemUiOverlayStyle(
          statusBarColor: _primary ? Colors.indigo : Colors.transparent,
          statusBarIconBrightness: _primary ? Brightness.light : Brightness.dark,
        ),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Card(
              color: Colors.indigo[50],
              child: Padding(
                padding: EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'primary 属性说明:',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                        color: Colors.indigo[800],
                      ),
                    ),
                    SizedBox(height: 10),
                    Text(
                      '• true: 这是主要的 Scaffold,处理状态栏样式',
                      style: TextStyle(fontSize: 14),
                    ),
                    Text(
                      '• false: 不是主要 Scaffold,不处理状态栏',
                      style: TextStyle(fontSize: 14),
                    ),
                    Text(
                      '• 通常在嵌套 Scaffold 或特殊布局时使用',
                      style: TextStyle(fontSize: 14),
                    ),
                  ],
                ),
              ),
            ),
            SizedBox(height: 20),
            SwitchListTile(
              title: Text(
                'primary 属性',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              subtitle: Text(
                _primary 
                  ? '当前是主要 Scaffold (处理状态栏)'
                  : '当前不是主要 Scaffold (不处理状态栏)',
              ),
              value: _primary,
              onChanged: (value) {
                setState(() {
                  _primary = value;
                });
              },
            ),
            SizedBox(height: 20),
            Container(
              padding: EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.grey[100],
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.grey[300]!),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    '当前状态:',
                    style: TextStyle(
                      fontWeight: FontWeight.bold,
                      fontSize: 16,
                    ),
                  ),
                  SizedBox(height: 10),
                  Text('primary: $_primary'),
                  Text('状态栏处理: ${_primary ? "是" : "否"}'),
                  Text('MediaQuery.of(context).padding.top: ${MediaQuery.of(context).padding.top}'),
                ],
              ),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => NestedScaffoldExample(),
                  ),
                );
              },
              child: Text('查看嵌套 Scaffold 示例'),
              style: ElevatedButton.styleFrom(
                backgroundColor: Colors.indigo,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class NestedScaffoldExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      primary: true, // 外层 Scaffold 是主要的
      appBar: AppBar(
        title: Text('嵌套 Scaffold 示例'),
        backgroundColor: Colors.indigo,
      ),
      body: Column(
        children: [
          Container(
            height: 100,
            color: Colors.indigo[100],
            child: Center(
              child: Text(
                '外层 Scaffold (primary: true)',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
            ),
          ),
          Expanded(
            child: Scaffold(
              primary: false, // 内层 Scaffold 不是主要的
              appBar: AppBar(
                title: Text('内层 AppBar'),
                backgroundColor: Colors.orange,
                automaticallyImplyLeading: false,
              ),
              body: Container(
                color: Colors.orange[100],
                child: Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Text(
                        '内层 Scaffold (primary: false)',
                        style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                      ),
                      SizedBox(height: 20),
                      Text(
                        '注意:内层 Scaffold 不处理状态栏样式',
                        textAlign: TextAlign.center,
                      ),
                    ],
                  ),
                ),
              ),
              floatingActionButton: FloatingActionButton(
                onPressed: () {},
                child: Icon(Icons.add),
                backgroundColor: Colors.orange,
                mini: true,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

6. extendBody - 扩展 body 到底部

控制 body 内容是否扩展到底部组件(如 bottomNavigationBar)的下方。

import 'package:flutter/material.dart';

class ExtendBodyExample extends StatefulWidget {
  @override
  _ExtendBodyExampleState createState() => _ExtendBodyExampleState();
}

class _ExtendBodyExampleState extends State<ExtendBodyExample> {
  bool _extendBody = false;
  int _selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('extendBody 示例'),
        backgroundColor: Colors.teal,
      ),
      extendBody: _extendBody,
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Colors.teal[50]!,
              Colors.teal[200]!,
            ],
          ),
        ),
        child: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Card(
                child: Padding(
                  padding: EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        'extendBody 属性控制:',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      SizedBox(height: 10),
                      SwitchListTile(
                        title: Text('扩展 body 到底部'),
                        subtitle: Text(
                          _extendBody
                              ? 'body 内容会延伸到底部导航栏下方'
                              : 'body 内容在底部导航栏上方结束',
                        ),
                        value: _extendBody,
                        onChanged: (value) {
                          setState(() {
                            _extendBody = value;
                          });
                        },
                      ),
                    ],
                  ),
                ),
              ),
              SizedBox(height: 20),
              Expanded(
                child: Container(
                  width: double.infinity,
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(12),
                    boxShadow: [
                      BoxShadow(
                        color: Colors.black12,
                        blurRadius: 10,
                        offset: Offset(0, 2),
                      ),
                    ],
                  ),
                  child: Padding(
                    padding: EdgeInsets.all(20),
                    child: Column(
                      children: [
                        Icon(
                          Icons.arrow_downward,
                          size: 40,
                          color: Colors.teal,
                        ),
                        SizedBox(height: 20),
                        Text(
                          '主要内容区域',
                          style: TextStyle(
                            fontSize: 24,
                            fontWeight: FontWeight.bold,
                            color: Colors.teal[800],
                          ),
                        ),
                        SizedBox(height: 20),
                        Text(
                          _extendBody
                              ? '当 extendBody = true 时,\n这个内容区域会延伸到底部导航栏下方,\n创建半透明效果。'
                              : '当 extendBody = false 时,\n这个内容区域在底部导航栏上方结束,\n不会被遮挡。',
                          textAlign: TextAlign.center,
                          style: TextStyle(fontSize: 16),
                        ),
                        Spacer(),
                        Container(
                          padding: EdgeInsets.all(16),
                          decoration: BoxDecoration(
                            color: _extendBody ? Colors.red[100] : Colors.green[100],
                            borderRadius: BorderRadius.circular(8),
                            border: Border.all(
                              color: _extendBody ? Colors.red : Colors.green,
                            ),
                          ),
                          child: Row(
                            children: [
                              Icon(
                                _extendBody ? Icons.visibility : Icons.visibility_off,
                                color: _extendBody ? Colors.red : Colors.green,
                              ),
                              SizedBox(width: 10),
                              Expanded(
                                child: Text(
                                  _extendBody
                                      ? '这部分内容可能被底部导航栏遮挡'
                                      : '这部分内容不会被底部导航栏遮挡',
                                  style: TextStyle(
                                    color: _extendBody ? Colors.red[800] : Colors.green[800],
                                    fontWeight: FontWeight.bold,
                                  ),
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedIndex,
        onTap: (index) {
          setState(() {
            _selectedIndex = index;
          });
        },
        type: BottomNavigationBarType.fixed,
        backgroundColor: _extendBody ? Colors.white.withOpacity(0.9) : Colors.white,
        selectedItemColor: Colors.teal,
        unselectedItemColor: Colors.grey,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            label: '首页',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            label: '搜索',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.favorite),
            label: '收藏',
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.person),
            label: '个人',
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _extendBody = !_extendBody;
          });
        },
        child: Icon(_extendBody ? Icons.expand_less : Icons.expand_more),
        backgroundColor: Colors.teal,
        tooltip: '切换 extendBody',
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }
}

7. extendBodyBehindAppBar - 扩展 body 到 AppBar 后面

控制 body 内容是否扩展到 AppBar 的后面。

import 'package:flutter/material.dart';

class ExtendBodyBehindAppBarExample extends StatefulWidget {
  @override
  _ExtendBodyBehindAppBarExampleState createState() => _ExtendBodyBehindAppBarExampleState();
}

class _ExtendBodyBehindAppBarExampleState extends State<ExtendBodyBehindAppBarExample> {
  bool _extendBodyBehindAppBar = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: _extendBodyBehindAppBar,
      appBar: AppBar(
        title: Text('extendBodyBehindAppBar 示例'),
        backgroundColor: _extendBodyBehindAppBar 
            ? Colors.purple.withOpacity(0.8) 
            : Colors.purple,
        elevation: _extendBodyBehindAppBar ? 0 : 4,
      ),
      body: Container(
        decoration: BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topCenter,
            end: Alignment.bottomCenter,
            colors: [
              Colors.purple[100]!,
              Colors.purple[50]!,
              Colors.white,
            ],
          ),
        ),
        child: SafeArea(
          top: false, // 不使用安全区域,让内容可以延伸到状态栏
          child: Padding(
            padding: EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                // 顶部间距,用于演示内容是否被 AppBar 遮挡
                SizedBox(height: _extendBodyBehindAppBar ? 100 : 20),
                Card(
                  color: Colors.white,
                  child: Padding(
                    padding: EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          'extendBodyBehindAppBar 控制:',
                          style: TextStyle(
                            fontSize: 18,
                            fontWeight: FontWeight.bold,
                            color: Colors.purple[800],
                          ),
                        ),
                        SizedBox(height: 10),
                        SwitchListTile(
                          title: Text('扩展 body 到 AppBar 后面'),
                          subtitle: Text(
                            _extendBodyBehindAppBar
                                ? 'body 从屏幕顶部开始,可能被 AppBar 遮挡'
                                : 'body 从 AppBar 下方开始,不会被遮挡',
                          ),
                          value: _extendBodyBehindAppBar,
                          onChanged: (value) {
                            setState(() {
                              _extendBodyBehindAppBar = value;
                            });
                          },
                        ),
                      ],
                    ),
                  ),
                ),
                SizedBox(height: 20),
                Expanded(
                  child: SingleChildScrollView(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        // 演示内容
                        _buildDemoSection('顶部内容区域', Icons.arrow_upward, 
                          _extendBodyBehindAppBar ? Colors.red : Colors.green),
                        SizedBox(height: 20),
                        _buildDemoSection('中间内容区域', Icons.center_focus_strong, Colors.blue),
                        SizedBox(height: 20),
                        _buildDemoSection('底部内容区域', Icons.arrow_downward, Colors.orange),
                        SizedBox(height: 20),
                        
                        // 实际应用场景示例
                        Container(
                          height: 200,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(12),
                            image: DecorationImage(
                              image: NetworkImage('https://picsum.photos/400/200'),
                              fit: BoxFit.cover,
                              onError: (exception, stackTrace) {
                                // 处理图片加载错误
                              },
                            ),
                          ),
                          child: Container(
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(12),
                              gradient: LinearGradient(
                                begin: Alignment.topCenter,
                                end: Alignment.bottomCenter,
                                colors: [
                                  Colors.transparent,
                                  Colors.black.withOpacity(0.7),
                                ],
                              ),
                            ),
                            child: Padding(
                              padding: EdgeInsets.all(16),
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.end,
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    '沉浸式体验',
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 24,
                                      fontWeight: FontWeight.bold,
                                    ),
                                  ),
                                  Text(
                                    'extendBodyBehindAppBar 常用于创建沉浸式的界面效果',
                                    style: TextStyle(
                                      color: Colors.white,
                                      fontSize: 14,
                                    ),
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _extendBodyBehindAppBar = !_extendBodyBehindAppBar;
          });
        },
        child: Icon(_extendBodyBehindAppBar ? Icons.vertical_align_bottom : Icons.vertical_align_top),
        backgroundColor: Colors.purple,
        tooltip: '切换 extendBodyBehindAppBar',
      ),
    );
  }

  Widget _buildDemoSection(String title, IconData icon, Color color) {
    return Container(
      width: double.infinity,
      padding: EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: color.withOpacity(0.1),
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: color, width: 2),
      ),
      child: Column(
        children: [
          Icon(icon, size: 40, color: color),
          SizedBox(height: 10),
          Text(
            title,
            style: TextStyle(
              fontSize: 18,
              fontWeight: FontWeight.bold,
              color: color,
            ),
          ),
          SizedBox(height: 5),
          Text(
            title == '顶部内容区域' 
                ? (_extendBodyBehindAppBar ? '可能被 AppBar 遮挡' : '不会被 AppBar 遮挡')
                : '正常显示区域',
            style: TextStyle(
              fontSize: 14,
              color: color.withOpacity(0.8),
            ),
            textAlign: TextAlign.center,
          ),
        ],
      ),
    );
  }
}
转存失败,建议直接上传图片文件 转存失败,建议直接上传图片文件

总结

Scaffold 是 Flutter 应用开发中最重要的布局组件之一,它提供了:

  1. 标准化的页面结构:符合 Material Design 规范
  2. 丰富的组件支持:AppBar、Drawer、FAB、BottomNavigationBar 等
  3. 灵活的配置选项:支持各种布局需求和交互模式
  4. 完善的状态管理:通过 ScaffoldState 管理组件状态
  5. 良好的扩展性:支持自定义和高级用法

七个重要属性总结

  • bottomSheet: 创建持久的底部表单面板
  • floatingActionButtonAnimator: 控制 FAB 的动画效果
  • persistentFooterButtons: 提供持久的底部操作按钮
  • resizeToAvoidBottomInset: 处理软键盘弹出时的布局调整
  • primary: 控制是否为主要 Scaffold,影响状态栏处理
  • extendBody: 让内容扩展到底部组件下方
  • extendBodyBehindAppBar: 让内容扩展到 AppBar 后面