Flutter圈子Flutter基础和实战Flutter中文社区

第二章●第一节:脚手架(Scaffold)

2019-04-29  本文已影响7人  白晓明
Scaffold用于实现基本的Material Design可视化结构,其提供了显示 drawers(抽屉),snack bars(提示信息)和bottom sheets(叠加层)的API。要显示snackbar或一个持久的bottom sheet,需要使用Scaffold静态的of方法来获取当前BuildContext的ScaffoldState(Scaffold的状态),并使用ScaffoldState.showSnackBar(用于在Scaffold底部显示SnackBar)和ScaffoldStates.showBottomSheet(用于在Scaffold中显示BottomSheet)函数。

我们先来看看官方给出的案例:

import 'package:flutter/material.dart';

//此示例显示了一个带有AppBar(标题栏),BottomAppBar(底部标题栏)和FloatingActionButton(悬浮按钮)的Scaffold。
//使用Center组件将文本组件放置在Scaffold 内容区正中,
//并且使用FloatingActionButtonLocation.centerDocked函数将FloatingActionButton位于BottomAppBar的正中。
//FloatingActionButton的点击事件调用一个递增的计数器,然后改变Scaffold内容区的数值。
void main() => runApp(MyApp());

class MyApp extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Code Sample for material.Scaffold",
      theme: ThemeData(
        primarySwatch: Colors.blue
      ),
      home: MyStatefulWidget(),
    );
  }
}

class MyStatefulWidget extends StatefulWidget{
  MyStatefulWidget({Key key}): super(key:key);

  @override
  _MyStatefulWidgetState createState() => _MyStatefulWidgetState();

}

class _MyStatefulWidgetState extends State<MyStatefulWidget>{
  int _count = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(//初始化Scaffold组件
      appBar: AppBar(//标题栏
        title: Text('Sample Code'),//使用Text组件显示标题栏文字
      ),
      body: Center(//使用Center组件将内容区文本居中
        child: Text('You have pressed the button $_count times.'),
      ),
      bottomNavigationBar: BottomAppBar(//底部标题栏
        child: Container(//内容区以Container组件填充,并设置高度
          height: 50.0,
        ),
      ),
      floatingActionButton: FloatingActionButton(//浮动按钮
        onPressed: () => setState(() {//浮动按钮点击事件
          _count++;
        }),
        //长按按钮显示的文字信息
        tooltip: 'Increment Counter',
        child: Icon(Icons.add),//浮动按钮内容区图标
      ),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,//设置浮动按钮位置
    );
  }
}

效果如下所示:

Scaffold应用
Scaffold将填充整个窗口或设备屏幕的可用空间。当设备键盘出现时,Scaffold会根据MediaQuery组件的MediaQueryData.viewInsets重绘Scaffold。默认情况下,Scaffold组件会调整大小以便为键盘腾出空间。我们也可以通过resizeToAvoidBottomInset设置为false来禁止调整大小,这样的话,Scaffold将不会再进行重绘。
//键盘出现时,是否重绘Scaffold
class ScaffoldKeyboard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "打开键盘重绘Scaffold",
      theme: ThemeData(
        primarySwatch: Colors.lightBlue
      ),
      home: Scaffold(
        body: Center(
          child: TextField(
            keyboardType: TextInputType.numberWithOptions(),
          ),
        ),
        resizeToAvoidBottomInset: true,//是否禁止Scaffold调整大小,true开启重绘,false禁止重绘
      ),
    );
  }
}

效果如下所示:

支持自动调整大小
不支持自动调整大小
Scaffold是MaterialApp组件的单顶级容器,因此其再不需要嵌套Scaffold。如果我们使用选项卡UI时,bottomNavigationBar时TabBar,而body中是TabBarView,我们需要为每个选项卡设置不同的标题文字,这时我们最好使用监听器添加选项卡到TabController中,以便每次选择后能够重置应用程序的AppBar标题。
void main() => runApp(MyTabbedPage());

//选项卡
class MyTabbedPage extends StatefulWidget {
  const MyTabbedPage({Key key}) : super(key: key);

  @override
  _MyTabbedPageState createState() => _MyTabbedPageState();
}

class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin {
  final List<Tab> myTabs = <Tab> [
    Tab(text: '首页', icon: Icon(Icons.home),),
    Tab(text: '消息', icon: Icon(Icons.message),),
    Tab(text: '我的', icon: Icon(Icons.account_circle),)
  ];

  TabController _tabController;
  String appBarTitle = "首页";
  @override
  void initState() {
    super.initState();
    //监听选项卡事件,选择选项卡重置AppBar标题
    _tabController = TabController(length: myTabs.length, vsync: this)..addListener(() {
      if(_tabController.indexIsChanging) {
        setState(() {
          appBarTitle = '${myTabs[_tabController.index].text}';
        });
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text(appBarTitle),
        ),
        bottomSheet: TabBar(
          tabs: myTabs,
          controller: _tabController,
        ),
        body: TabBarView(
          controller: _tabController,
          children: myTabs.map((Tab tab) {
            return Center(child: Text(tab.text),);
          }).toList(),
        ),
      ),
    );
  }
}

效果图如下:

首页
消息

Scaffold属性

Scaffold属性

本节内容到此结束,若在使用过程中遇到问题,欢迎留言交流,我们一起成长。


总目录结构

上一篇下一篇

猜你喜欢

热点阅读