第二章●第二节:应用栏(Appbar)

AppBar由工具栏和其他组件组成,如TabBarFlexibleSpaceBarAppBar通常使用IconButtons公开一个或多个常见的操作,也可以使用PopupMenuButton,用于不常见的操作(有时称为“溢出菜单”)。

TabBar:一个显示水平Tabs的Material Design组件。通常使用AppBar.bottomTabBarView(用来显示与每个TabBar对应的页面视图)结合实现AppBar底部的切换选项卡。在TabBarTabBarView结合使用时,若未提供TabController,则必须提供父级DefaultTabController。并且选项卡控制器的TabController.length必须等于选项卡列表的长度。

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

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(
      home: Scaffold(
        appBar: AppBar(
          title: Text(appBarTitle),
          bottom: TabBar(
            tabs: myTabs,//两个或多个Tab组件的列表
            controller: _tabController,//组件的选择和动画状态
            isScrollable: true,//选项卡是否可以水平滚动,若为true,则每个选项卡宽度与其标签一样宽,并且整个TabBar都可以滚动。否则每个选项卡将根据可用空间被等分
            indicatorColor: Colors.red,//显示在选项卡下边的线条颜色,如果设置为null,则使用Theme的indicatorColor属性的颜色值
            indicatorWeight: 2.0,//选项卡下边线条的权重,也就是粗细
            indicatorPadding: EdgeInsets.all(5.0),//选中选项卡下边的线条水平填充
            //定义所选选项卡指示器的外观,如果指定该属性值,则忽略indicatorColor,indicatorWeight和indicatorPadding属性
            //可以使用UnderlineTabIndicator定义默认值,下划线样式,选中Tab标签的线条样式
            //indicator: BoxDecoration(color: Colors.amber, border: Border.all(width: 2.0, color: Colors.deepOrange)),
            indicatorSize: TabBarIndicatorSize.tab,//定义选中选项卡下边线条的宽度,与文本标签一样宽,与tab标签一样宽
            labelColor: Colors.deepPurple,//选中Tab中文本标签样式
            labelStyle: TextStyle(fontWeight: FontWeight.bold, fontSize: 16.0),//所选标签的文本样式
            labelPadding: EdgeInsets.all(10.0),//选项卡文本标签内边距
            unselectedLabelStyle: TextStyle(fontSize: 12.0),//未选中的Tab文本标签样式
            unselectedLabelColor: Colors.deepOrangeAccent,//未选中的Tab文本标签颜色
            dragStartBehavior: DragStartBehavior.down,//确定处理拖动开始行为方式
          ),

        ),
        body: TabBarView(
          controller: _tabController,
          children: myTabs.map((Tab tab) {
            return Center(child: Text(tab.text),);
          }).toList(),
        ),
      ),
    );
  }
}

效果图如下:

TabBar

用于扩展和折叠Material Design AppBar,常用于SliverAppBar.flexibleSpace属性来灵活控制组件的滚动而展开和收缩。

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

void main() => runApp(MyFlexibleSpaceBar());

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

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

class _MyFlexiblePaceBarPageState extends State<MyFlexibleSpaceBar> with SingleTickerProviderStateMixin {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('FlexibleSpaceBar组件'),
        ),
        body: NestedScrollView(
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return <Widget> [
              SliverAppBar(
                expandedHeight: 150.0,
                floating: false,
                pinned: true,
                flexibleSpace: FlexibleSpaceBar(
                  centerTitle: true,
                  title: Text(
                    "可折叠的组件"
                  ),
                ),
                backgroundColor: Colors.red,
              ),
            ];
          },
          body: Center(
            child: Text("向上拖动,查看效果"),
          ),
        ),
      ),
    );
  }
}

效果如下:

FlexibleSpaceBar
从上边示例我们可以看出,通常使用Scaffold.appBar属性,将AppBar放置在屏幕顶部并固定高度。对于可以滚动的AppBar,我们可以使用SliverAppBar
我们可以在AppBar上显示工具栏组件,标题组件前显示的组件,标题组件,标题组件后显示的操作组件以及AppBar底部的组件(如果有的话)。如果指定了flexibleSpace窗口组件,则它将堆叠在工具栏和底部窗口组件后。
AppBar布局
如果我们省略了leading组件,但应用程序中我们实现了抽屉式的组件,则会自动在leading组件位置插入一个打开抽屉的按钮。可以通过automatedImplyLeading设置为false来关闭此行为。
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyAppBar());

class MyAppBar extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          actions: <Widget>[
            IconButton(icon: Icon(Icons.add), onPressed: () {

            }),
          ],
          leading: Icon(Icons.face),
          centerTitle: false,//控制文本标签是否居中
          title: Text("AppBar组件"),
          flexibleSpace: Icon(Icons.print),
          bottom: PreferredSize(
            child: Text("我是AppBar Bottom"),
            preferredSize: Size(10.0, 10.0),
          ),
        ),
      ),
    );
  }
}

效果如下:

AppBar

AppBar 属性

AppBar属性

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


总目录结构

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355