Scaffold

一个实现了基本Material Design视觉布局结构的组件

Scaffold提供了展示抽屉和底部的功能。通过Scaffold.of获取当前BuildContextScaffoldState,并使用ScaffoldState.showBottomSheet函数,可以展示底部抽屉,。

Scaffold布局,键盘以及刘海区域的显示

Scaffold将扩展以填充可用空间。这意味着它将占据整个窗口。当键盘出现的时候,Scaffold的祖先组件MediaQueryMediaQueryData.viewInsets值会改变,此时Scaffold会被重建。默认情况下,Scaffold会调整大小腾出空间给键盘。如果不想Scaffold调整大小,可以将resizeToAvoidBottomInset设置为false。在任何情况下,如果有焦点组件在可滚动容器内,它将被滚动到视图中。

MediaQueryData.padding值定义了可能不会完全显示的区域,比如iphone上的刘海。通常情况下,Scaffoldbody区域因为AppBar或者BottomNavigationBar可以避免碰触到这些不显示的区域,但是如果想要完全避免这种情况发生,可以使用SafeArea组件。

设置可拖动可滚动底部抽屉时同时设置悬浮按钮

如果Scaffold.bottomSheet是一个可拖动且可滚动的底部抽屉且同时设置了Scaffold.floatingActionButton。当底部抽屉拖动超过Scaffold高度的70%时,两件事将会发生:

  • Scaffold将会展示遮罩
  • Scaffold.floatingActionButton将会以Curves.easeIn动画缩小,并且将会在底部抽屉完全盖住Scaffold时完全消失

一旦拖动底部抽屉覆盖小于高度的70%,那么遮罩将会消失且Scaffold.floatingActionButton将会恢复正常大小。

例子

例子1

import 'package:flutter/material.dart';

/// Flutter code sample for [Scaffold].

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

class ScaffoldExampleApp extends StatelessWidget {
  const ScaffoldExampleApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(home: ScaffoldExample());
  }
}

class ScaffoldExample extends StatefulWidget {
  const ScaffoldExample({super.key});

  
  State<ScaffoldExample> createState() => _ScaffoldExampleState();
}

class _ScaffoldExampleState extends State<ScaffoldExample> {
  int _count = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Sample Code')),
      body: Center(child: Text('You have pressed the button $_count times.')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => _count++),
        tooltip: 'Increment Counter',
        child: const Icon(Icons.add),
      ),
    );
  }
}

例子2

import 'package:flutter/material.dart';

/// Flutter code sample for [Scaffold].

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

class ScaffoldExampleApp extends StatelessWidget {
  const ScaffoldExampleApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(home: ScaffoldExample());
  }
}

class ScaffoldExample extends StatefulWidget {
  const ScaffoldExample({super.key});

  
  State<ScaffoldExample> createState() => _ScaffoldExampleState();
}

class _ScaffoldExampleState extends State<ScaffoldExample> {
  int _count = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Sample Code')),
      body: Center(child: Text('You have pressed the button $_count times.')),
      backgroundColor: Colors.blueGrey.shade200,
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() => _count++),
        tooltip: 'Increment Counter',
        child: const Icon(Icons.add),
      ),
    );
  }
}

例子3

import 'package:flutter/material.dart';

/// Flutter code sample for [Scaffold].

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

class ScaffoldExampleApp extends StatelessWidget {
  const ScaffoldExampleApp({super.key});

  
  Widget build(BuildContext context) {
    return const MaterialApp(home: ScaffoldExample());
  }
}

class ScaffoldExample extends StatefulWidget {
  const ScaffoldExample({super.key});

  
  State<ScaffoldExample> createState() => _ScaffoldExampleState();
}

class _ScaffoldExampleState extends State<ScaffoldExample> {
  int _count = 0;

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Sample Code')),
      body: Center(child: Text('You have pressed the button $_count times.')),
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(),
        child: Container(height: 50.0),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => setState(() {
          _count++;
        }),
        tooltip: 'Increment Counter',
        child: const Icon(Icons.add),
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
    );
  }
}

构造函数

Scaffold.new({
  Key? key, 
  PreferredSizeWidget? appBar, 
  Widget? body, 
  Widget? floatingActionButton, 
  FloatingActionButtonLocation? floatingActionButtonLocation, 
  FloatingActionButtonAnimator? floatingActionButtonAnimator, 
  List<Widget>? persistentFooterButtons, 
  AlignmentDirectional persistentFooterAlignment = AlignmentDirectional.centerEnd, 
  BoxDecoration? persistentFooterDecoration, 
  Widget? drawer, 
  DrawerCallback? onDrawerChanged, 
  Widget? endDrawer, 
  DrawerCallback? onEndDrawerChanged, 
  Widget? bottomNavigationBar, 
  Widget? bottomSheet, 
  Color? backgroundColor, 
  bool? resizeToAvoidBottomInset, 
  bool primary = true, 
  DragStartBehavior drawerDragStartBehavior = DragStartBehavior.start, 
  bool extendBody = false, 
  bool drawerBarrierDismissible = true, 
  bool extendBodyBehindAppBar = false, 
  Color? drawerScrimColor, 
  Widget? bottomSheetScrimBuilder(BuildContext, Animation<double>) = _defaultBottomSheetScrimBuilder, 
  double? drawerEdgeDragWidth, 
  bool drawerEnableOpenDragGesture = true, 
  bool endDrawerEnableOpenDragGesture = true, 
  String? restorationId
})

属性

属性名类型解释
appBarPreferredSizeWidget?顶部的AppBar
backgroundColorColor?Scaffold背景色
bodyWidget?Scaffold中间的主体组件
bottomNavigationBarWidget?Scaffold底部导航栏
bottomSheetWidget?Scaffold底部抽屉
bottomSheetScrimBuilderWidget? Function(BuildContext, Animation<double>)一个builder函数用于创建底部抽屉的遮罩
drawerWidget?body侧面滑出的一个面板抽屉,默认从左往右滑出
drawerBarrierDismissiblebool是否可以通过点击遮罩关闭抽屉
drawerDragStartBehaviorDragStartBehavior设置何时才判定为抽屉滑动,down用户触摸到屏幕即开始算,start用户触摸到屏幕并拖动一段距离开始算
drawerEdgeDragWidthdouble?从屏幕边缘拖动多少距离打开抽屉,如果设置为0,那么将禁用从屏幕边缘滑动打开抽屉的功能
drawerEnableOpenDragGesturebool设置是否允许从屏幕边缘滑动打开抽屉的功能
drawerScrimColorColor?抽屉遮罩颜色
endDrawerWidget?body侧面滑出的一个面板抽屉,默认从右往左滑出
endDrawerEnableOpenDragGesturebool同上
extendBodybool设置body内容是否延伸到底部导航栏下面,通常用于将导航栏设置为透明或者毛玻璃风格
extendBodyBehindAppBarbool设置body内容是否延伸到AppBar下面,通常用于将导航栏设置为透明或者毛玻璃风格
floatingActionButtonWidget?body右下角展示的一个悬浮按钮
floatingActionButtonLocationFloatingActionButtonLocation?设置悬浮按钮展示位置
floatingActionButtonAnimatorFloatingActionButtonAnimator?设置悬浮按钮移动到新位置的动画
onDrawerChangedDrawerCallback?Scaffold.drawer打开或关闭时,调用该回调函数
onEndDrawerChangedDrawerCallback?Scaffold.endDrawer打开或关闭时,调用该回调函数
persistentFooterAlignmentAlignmentDirectional设置底部按钮的排列方式
persistentFooterButtonsList<Widget>?设置底部按钮
persistentFooterDecorationBoxDecoration?设置包含底部按钮的Container的装饰样式
primarybool设置这个Scaffold是否在屏幕最顶层展示
resizeToAvoidBottomInsetbool?设置为false时,弹出键盘时,Scaffold.body不会调整大小来腾出空间给键盘
restorationIdString?用于保存和恢复 Scaffold 状态的恢复 ID

静态方法

函数名类型解释
geometryOf(BuildContext context) -> ValueListenable<ScaffoldGeometry>返回给定上下文中最近的Scaffold祖先的ScaffoldGeometryValueListenable
hasDrawer(BuildContext context, {bool registerForUpdates = true }) -> bool返回给定上下文最近的Scaffold是否有抽屉
maybeOf(BuildContext context) -> ScaffoldState?返回给定上下文最近的ScaffoldScaffoldState, 可能为空
of(BuildContext context) -> ScaffoldState返回给定上下文最近的ScaffoldScaffoldState