likes
comments
collection
share

Flutter AppBar 参数详解与示例 | Flutter Widget

作者站长头像
站长
· 阅读数 11

Flutter AppBar 参数详解与示例

AppBar 介绍

Flutter AppBar 参数详解与示例 | Flutter Widget

AppBar 是 实现了 PreferredSizeWidgetStatefulWidget。一般用于传给 Scaffold ,显示于屏幕的顶部横向长条组件,可以返回,显示当前页面标题。有多种称谓,如标题栏、顶部导航栏、状态栏。

也可以“反设计”,appBar 不放到 Scaffold 中,放到屏幕底部,或者其他位置,都是可以实现但不符合习惯。

参数定义

leading AppBar 左边的 widget,一般用于显示 返回键

leadingWidth leading 最大宽度,最宽是屏幕宽度的 1/3

toolbarHeight AppBar 中的 toolbar 的高度,当没有 bottom 时 等于 AppBar 的高度,当有 bottom 时,toolbarHeight 加上 bottom 的高度才是 appBar 的高度

automaticallyImplyLeading leading 是 null 时 是否自动创建 leading,比如有 可以回退时自动创建返回键,有 抽屉栏 drawer 时会自动创建 “三“ 图标,点击展示抽屉栏

title 标题 widget

centerTitle 标题是否居中,当有 leading 和 actions 时,剩余的空间不多时,即使设置了 centerTitle ,title 也不居中。

actions widget 列表,AppBar 会把 actions 放到 row 中,宽度最宽为屏幕宽度。

flexibleSpace 和 AppBar 一起在 stack 里,在 AppBar 下面,可以用来放个背景图。 另外类似常见的可以缩放 AppBar 的应用场景可以使用 FlexibleSpaceBar

bottom AppBar 下面的 PreferredSizeWidget ,一般应用场景是 TabBar

elevation 标题栏下的阴影高度,设置为 0 则没有阴影

scrolledUnderElevation (未实践)有其他组件在 AppBar 下面滚动时用到

shadowColor AppBar 下阴影颜色

surfaceTintColor 通过改变 AppBar 的背景颜色来表明高度。 ThemeData 中useMaterial3:true 才生效,设置后UI风格改变会很大。

shape AppBar 的形状,可以设置为圆形,圆角等。

backgroundColor AppBar 的背景色

foregroundColor AppBar 中 文本和 Icon 的颜色

brightness 废弃,明暗主题

iconTheme 设置 icon (包含 leading 和 actions)的颜色、透明度、大小、阴影

actionsIconTheme 与iconTheme 类似

textTheme 废弃

primary AppBar 是否在屏幕顶部,如果为 true AppBar 会在 顶部的padding 中加上 状态栏的高度,目前的实现方式是采用 SafeArea 包住 AppBar

excludeHeaderSemantics 是否排除 Semantics,辅助模式相关的,一般是用来帮助视力不好的用户使用 app。

titleSpacing title 水平的 padding,默认为 NavigationToolbar.kMiddleSpacing ,设置为 0.0 则无距离

toolbarOpacity toolbar 的透明度,toolbar 中的widget 是 leading、title、actions、不包含 flexibleSpace 和bottom。

bottomOpacity bottom 的透明度

toolbarTextStyle AppBar 中的除 title以外 的 Text 的 TextStyle,目前就是 leading 和 actions 中的 TextStyle。

titleTextStyle title 中的 Text 的style。

systemOverlayStyle 系统状态栏 和 底部虚拟栏颜色,在某些定制手机中可能会不生效。

以下对 常用的、容易出问题的、不能顾名思义的参数进行示例说明

无参数 AppBar UI

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
			...
    );
  }

Flutter AppBar 参数详解与示例 | Flutter Widget

leading|leadingWidth|automaticallyImplyLeading

leading 可以任意类型 Widget,leading 默认宽高都是 kToolbarHeight 即 56.0, 最大宽高由 参数 toolbarHeight 和 leadingWidth 设置。

leading 最大宽度为 AppBar 的 1/3 ,也就是默认情况下 leadingWidth 即使设置的非常大也不生效。使用 UnconstrainedBox 可以突破 1/3 限制。

if (hasChild(_ToolbarSlot.leading)) {
      final BoxConstraints constraints = BoxConstraints(
        maxWidth: size.width / 3.0, // The leading widget shouldn't take up more than 1/3 of the space.
        minHeight: size.height, // The height should be exactly the height of the bar.
        maxHeight: sizAppBar(
        leadingWidth: 300,
        toolbarHeight: 100,
        leading: UnconstrainedBox(
          child: Container(
            width: 300,
            height: 100,
            color: Colors.red,
            child: const Icon(
              Icons.arrow_back,
            ),
          ),
        ),
        title: const Text('large leading demo '),
      )e.height,
      );
      leadingWidth = layoutChild(_ToolbarSlot.leading, constraints).width;
		...
    }

示例 - 较大的 leading

leading 超大时 title 会覆盖 leading,这种情况不适合用 AppBar 。

看到界面中有 overflowed 的提示,release 包运行是正常的,没有白屏问题。

AppBar(
  leadingWidth: 300,
  toolbarHeight: 100,
  leading: UnconstrainedBox(
    child: Container(
      width: 300,
      height: 100,
      color: Colors.red,
      child: const Icon(
        Icons.arrow_back,
      ),
    ),
  ),
  title: const Text('leading demo'),
)

Flutter AppBar 参数详解与示例 | Flutter Widget

示例 - leading 多 组件

当 leading 里需要多个组件时高度会超过 默认的 56,需要手动设置 leadingWidth 为指定宽度。

AppBar(
  leadingWidth: 64,
  leading: Container(
    color: Colors.red,
    child: Row(
      children: const <Widget>[
        SizedBox(
          width: 32,
          height: 32,
          child: Icon(
            Icons.arrow_back,
          ),
        ),
        SizedBox(
          width: 32,
          height: 32,
          child: Icon(
            Icons.arrow_downward_outlined,
          ),
        ),
      ],
    ),
  ),
  title: const Text('double leading demo'),
)

Flutter AppBar 参数详解与示例 | Flutter Widget

leading 自动添加 返回键或 menu 键

当我们没有设置 leading 时,leading 也有内容显示是因为 automaticallyImplyLeading 为 true 时会判断是否有 drawer 和是否能 pop,右 drawer 则显示 menu 图标,能 pop 则显示 back 图标

if (leading == null && widget.automaticallyImplyLeading) {
  if (hasDrawer) {
    leading = IconButton(
      icon: const Icon(Icons.menu),
      iconSize: overallIconTheme.size ?? 24,
      onPressed: _handleDrawerButton,
      tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
    );
  } else {
    if (!hasEndDrawer && canPop)
      leading = useCloseButton ? const CloseButton() : const BackButton();
  }
}

title|centerTitle | titleSpacing

示例 - 特别长的 title

AppBar(
  title: Text('超长的标题' * 5),
)

Flutter AppBar 参数详解与示例 | Flutter Widget

从示例中看到 标题左右的边距不同,是因为 leadingWidth 默认为 56,actions 默认没有宽度。如果希望 title 与 leading 和 action 一样,需要单独设置leadingWidth 的宽度与 leading 内容相同。

actions

actions 是 AppBar 中右边 widget,一般用于点击后去执行某些动作,如添加,编辑等。

actions 在 AppBar 中的实现是 放到 Row 中。

示例 - 特多的 action 情况

AppBar(
  titleSpacing: 0,
  centerTitle: true,
  actions: const [
    Icon(
      Icons.add,
    ),
    Icon(
      Icons.add,
    ),
    Icon(
      Icons.delete,
    ),
    Icon(
      Icons.delete,
    ),
    Icon(
      Icons.delete,
    ),
    Icon(
      Icons.delete,
    ),
    Icon(
      Icons.delete,
    ),
    Icon(
      Icons.delete,
    ),

  ],
  title: const Text('multi actions'),
);

Flutter AppBar 参数详解与示例 | Flutter Widget

action 较多时会挤占 title 的空间,即使设置了 centerTitle: true, title 也不居中了。

primary

primary 默认为 true,把 AppBar 放到 safeArea 里。

primary 为 false 时,AppBar 不放 safeArea 里,AppBar 内容会上移。

AppBar(
  primary: false,
  title: const Text('primary demo'),
);

Flutter AppBar 参数详解与示例 | Flutter Widget

bottom

AppBar(
  title: const Text('bottom demo'),
  bottom: TabBar(
    tabs: const [Text('Tab 1'), Text('Tab 2'), Text('Tab 3')],
    controller:
        TabController(vsync: this, initialIndex: 0, length: 3),
  ),
);

Flutter AppBar 参数详解与示例 | Flutter Widget

可以看到 title 和 底下 tab 间隔较大。这里涉及了 AppBar 和 bottom 的高度的 关系

AppBar 和 bottom 都继承自PreferredSizeWidget ,重载了 preferredSize

其中 AppBar 的高度为 toolbarHeight ?? kToolbarHeight) + (bottomHeight ?? 0)

本示例中的 TabBar 默认高度为 46,内部的tab项高度小于 46,所以显示出的间隔较大。因为 TabBar 没有参数修改 preferedSize,所以可以通过使用 PreferredSize 把 TabBar 包起来重写 PreferredSize,当然也可以通过 继承 TabBar 。

AppBar(
  backgroundColor: Colors.blueAccent,
  title: const Text('bottom demo'),
  bottom: PreferredSize(
    preferredSize: Size.fromHeight(32),
    child: Container(
      child: TabBar(
        indicatorSize: TabBarIndicatorSize.tab,
        tabs: [
          Container(
            height: 32,
            alignment: Alignment.center,
            child: Text('Tab 1'),
          ),
          Container(
            height: 32,
            alignment: Alignment.center,
            child: Text('Tab 2'),
          ),
          Container(
            height: 32,
            alignment: Alignment.center,
            child: Text('Tab 3'),
          )
        ],
        controller:
            TabController(vsync: this, initialIndex: 0, length: 3),
      ),
    ),
  ),
);

Flutter AppBar 参数详解与示例 | Flutter Widget

最后

有问题请指正,谢谢