You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter自定义工具栏创建及指定样式AppBar实现与按钮显隐控制

嘿,我来帮你搞定这个自定义AppBar的问题!要实现你想要的样式,同时还能单独控制每个按钮的显隐,其实可以通过Flutter的AppBar结合状态管理来轻松实现,下面一步步给你拆解:

一、核心思路:用状态变量控制按钮显隐

默认的AppBar的actions属性接受一个Widget数组,我们可以通过布尔状态变量结合条件判断,来决定每个按钮是否显示。只要在需要切换状态时调用setState(),就能实时更新UI。

二、完整代码示例(基础自定义AppBar)

先给你一个可直接运行的示例,包含了自定义样式+动态控制按钮显隐的逻辑:

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const CustomAppBarDemo(),
      theme: ThemeData(primarySwatch: Colors.blue),
    );
  }
}

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

  @override
  State<CustomAppBarDemo> createState() => _CustomAppBarDemoState();
}

class _CustomAppBarDemoState extends State<CustomAppBarDemo> {
  // 定义状态变量,控制每个按钮的显隐
  bool _showSearchBtn = true;
  bool _showFavoriteBtn = true;
  bool _showShareBtn = false; // 默认隐藏分享按钮

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.blue[700], // 自定义背景色
        elevation: 4, // 控制阴影深度,增强层次感
        leading: IconButton(
          icon: const Icon(Icons.menu, color: Colors.white),
          onPressed: () {
            // 左侧菜单按钮逻辑
            Scaffold.of(context).openDrawer();
          },
        ),
        title: const Text(
          "我的应用",
          style: TextStyle(color: Colors.white, fontSize: 18),
        ),
        centerTitle: true, // 让标题居中显示
        actions: [
          // 搜索按钮:根据_showSearchBtn判断是否显示
          if (_showSearchBtn)
            IconButton(
              icon: const Icon(Icons.search, color: Colors.white),
              onPressed: () => _showToast("点击了搜索"),
            ),
          // 收藏按钮:根据_showFavoriteBtn判断是否显示
          if (_showFavoriteBtn)
            IconButton(
              icon: const Icon(Icons.favorite_border, color: Colors.white),
              onPressed: () => _showToast("点击了收藏"),
            ),
          // 分享按钮:根据_showShareBtn判断是否显示
          if (_showShareBtn)
            IconButton(
              icon: const Icon(Icons.share, color: Colors.white),
              onPressed: () => _showToast("点击了分享"),
            ),
          // 用来切换按钮状态的测试按钮
          IconButton(
            icon: const Icon(Icons.settings, color: Colors.white),
            onPressed: () {
              setState(() {
                // 切换所有按钮的显隐状态
                _showSearchBtn = !_showSearchBtn;
                _showFavoriteBtn = !_showFavoriteBtn;
                _showShareBtn = !_showShareBtn;
              });
            },
          ),
        ],
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            setState(() {
              // 单独控制分享按钮的显隐
              _showShareBtn = !_showShareBtn;
            });
          },
          child: const Text("切换分享按钮显隐"),
        ),
      ),
    );
  }

  // 简单的提示工具方法
  void _showToast(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }
}
三、关键细节说明
  • 动态显隐控制:通过if条件判断结合setState(),你可以在任何地方(比如接口回调、用户操作、页面状态变化)单独控制某个按钮的显示或隐藏,完全灵活。
  • 自定义样式调整:
    • backgroundColor:设置AppBar的背景色,适配你的UI风格;
    • elevation:控制阴影高度,让AppBar有悬浮感;
    • leading:自定义左侧的按钮(比如菜单、返回键);
    • centerTitle:决定标题是否居中,满足不同的布局需求;
    • 每个IconButton可以自定义图标颜色、大小,甚至换成自定义图片(用ImageIcon组件)。
  • 复杂布局适配:如果按钮之间需要间距、或者要混合文本按钮,你可以把actions里的内容换成Row组件,配合Padding、SizedBox来调整布局,比如:
actions: [
  Row(
    children: [
      if (_showSearchBtn)
        Padding(
          padding: const EdgeInsets.only(right: 12.0),
          child: IconButton(icon: const Icon(Icons.search), onPressed: () {}),
        ),
      // 其他按钮...
    ],
  )
]
四、进阶:完全自定义Toolbar(突破AppBar限制)

如果默认AppBar的布局或高度满足不了你的需求,还可以用PreferredSizeWidget创建一个完全自定义的工具栏,示例如下:

class CustomToolbar extends StatelessWidget implements PreferredSizeWidget {
  final bool showSearch;
  final bool showFavorite;
  final VoidCallback? onSearchPressed;
  final VoidCallback? onFavoritePressed;

  const CustomToolbar({
    super.key,
    required this.showSearch,
    required this.showFavorite,
    this.onSearchPressed,
    this.onFavoritePressed,
  });

  @override
  Widget build(BuildContext context) {
    return Container(
      height: preferredSize.height,
      color: Colors.blue[700],
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          // 左侧菜单按钮
          IconButton(
            icon: const Icon(Icons.menu, color: Colors.white),
            onPressed: () => Scaffold.of(context).openDrawer(),
          ),
          // 中间标题
          const Text(
            "自定义工具栏",
            style: TextStyle(color: Colors.white, fontSize: 18),
          ),
          // 右侧按钮组
          Row(
            children: [
              if (showSearch)
                IconButton(
                  icon: const Icon(Icons.search, color: Colors.white),
                  onPressed: onSearchPressed,
                ),
              if (showFavorite)
                IconButton(
                  icon: const Icon(Icons.favorite_border, color: Colors.white),
                  onPressed: onFavoritePressed,
                ),
            ],
          ),
        ],
      ),
    );
  }

  // 自定义工具栏高度,也可以用默认的kToolbarHeight
  @override
  Size get preferredSize => const Size.fromHeight(60);
}

然后在Scaffold中直接使用:

Scaffold(
  appBar: CustomToolbar(
    showSearch: _showSearchBtn,
    showFavorite: _showFavoriteBtn,
    onSearchPressed: () => _showToast("搜索"),
  ),
  // 页面内容...
)

这种方式能让你完全掌控工具栏的布局、高度和样式,适合更复杂的UI需求。

内容的提问来源于stack exchange,提问作者Sarath Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 07:38:14