Flutter AppBar 导航栏组件完全指南

什么是 AppBar?

AppBar 是 Flutter 中的顶部导航栏组件,通常放在 Scaffold 的 appBar 属性中。

用途:

  • 显示页面标题
  • 返回按钮
  • 操作按钮
  • 搜索功能
  • 标签切换

基础用法

dart 复制代码
Scaffold(
  appBar: AppBar(
    title: Text('标题'),
  ),
  body: Container(),
)

常用属性

1. title - 标题

dart 复制代码
AppBar(
  title: Text('我的应用'),
)

2. leading - 左侧组件

dart 复制代码
AppBar(
  leading: IconButton(
    icon: Icon(Icons.menu),
    onPressed: () {},
  ),
  title: Text('标题'),
)

3. actions - 右侧操作按钮

dart 复制代码
AppBar(
  title: Text('标题'),
  actions: [
    IconButton(
      icon: Icon(Icons.search),
      onPressed: () {},
    ),
    IconButton(
      icon: Icon(Icons.more_vert),
      onPressed: () {},
    ),
  ],
)

4. backgroundColor - 背景颜色

dart 复制代码
AppBar(
  title: Text('标题'),
  backgroundColor: Colors.blue,
)

5. centerTitle - 标题居中

dart 复制代码
AppBar(
  title: Text('标题'),
  centerTitle: true,  // 标题居中
)

6. elevation - 阴影高度

dart 复制代码
AppBar(
  title: Text('标题'),
  elevation: 0,  // 无阴影
)

7. bottom - 底部组件

dart 复制代码
AppBar(
  title: Text('标题'),
  bottom: TabBar(
    tabs: [
      Tab(text: '标签1'),
      Tab(text: '标签2'),
      Tab(text: '标签3'),
    ],
  ),
)

实战案例

案例1:基础导航栏

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: BasicAppBarPage(),
    );
  }
}

class BasicAppBarPage extends StatelessWidget {
  const BasicAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('首页'),
        centerTitle: true,
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: () {
            print('打开菜单');
          },
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {
              print('搜索');
            },
          ),
          IconButton(
            icon: const Icon(Icons.notifications),
            onPressed: () {
              print('通知');
            },
          ),
        ],
      ),
      body: const Center(child: Text('基础导航栏示例')),
    );
  }
}

案例2:渐变导航栏

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: GradientAppBarPage(),
    );
  }
}

class GradientAppBarPage extends StatelessWidget {
  const GradientAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('渐变导航栏'),
        centerTitle: true,
        flexibleSpace: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.blue, Colors.purple],
              begin: Alignment.topLeft,
              end: Alignment.bottomRight,
            ),
          ),
        ),
      ),
      body: const Center(child: Text('渐变导航栏示例')),
    );
  }
}

案例3:透明导航栏

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: TransparentAppBarPage(),
    );
  }
}

class TransparentAppBarPage extends StatelessWidget {
  const TransparentAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        title: const Text('透明导航栏'),
        backgroundColor: Colors.transparent,
        elevation: 0,
      ),
      body: Container(
        decoration: const BoxDecoration(
          image: DecorationImage(
            image: NetworkImage('https://picsum.photos/400/800'),
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

案例4:搜索导航栏

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: SearchAppBar(),
    );
  }
}

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

  @override
  State<SearchAppBar> createState() => _SearchAppBarState();
}

class _SearchAppBarState extends State<SearchAppBar> {
  bool _isSearching = false;
  final TextEditingController _searchController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: _isSearching
            ? TextField(
                controller: _searchController,
                autofocus: true,
                decoration: const InputDecoration(
                  hintText: '搜索...',
                  border: InputBorder.none,
                  hintStyle: TextStyle(color: Colors.white70),
                ),
                style: const TextStyle(color: Colors.white),
                onSubmitted: (value) {
                  print('搜索: $value');
                },
              )
            : const Text('搜索示例'),
        actions: [
          IconButton(
            icon: Icon(_isSearching ? Icons.close : Icons.search),
            onPressed: () {
              setState(() {
                _isSearching = !_isSearching;
                if (!_isSearching) {
                  _searchController.clear();
                }
              });
            },
          ),
        ],
      ),
      body: const Center(child: Text('内容')),
    );
  }

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

案例5:带 TabBar 的导航栏

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: TabBarPage(),
    );
  }
}

class TabBarPage extends StatelessWidget {
  const TabBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('标签页'),
          bottom: const TabBar(
            tabs: [
              Tab(icon: Icon(Icons.home), text: '首页'),
              Tab(icon: Icon(Icons.explore), text: '发现'),
              Tab(icon: Icon(Icons.person), text: '我的'),
            ],
          ),
        ),
        body: const TabBarView(
          children: [
            Center(child: Text('首页')),
            Center(child: Text('发现')),
            Center(child: Text('我的')),
          ],
        ),
      ),
    );
  }
}

案例6:可滚动的 AppBar

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ScrollableAppBarPage(),
    );
  }
}

class ScrollableAppBarPage extends StatelessWidget {
  const ScrollableAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          SliverAppBar(
            expandedHeight: 200,
            floating: false,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
              title: const Text('可滚动导航栏'),
              background: Image.network(
                'https://picsum.photos/400/200',
                fit: BoxFit.cover,
              ),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return ListTile(
                  title: Text('项目 $index'),
                );
              },
              childCount: 50,
            ),
          ),
        ],
      ),
    );
  }
}

案例7:自定义高度的 AppBar

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: CustomHeightAppBarPage(),
    );
  }
}

class CustomHeightAppBarPage extends StatelessWidget {
  const CustomHeightAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('自定义高度'),
        toolbarHeight: 80, // 自定义高度
        leading: Padding(
          padding: const EdgeInsets.all(8),
          child: CircleAvatar(
            backgroundImage: const NetworkImage('https://picsum.photos/100'),
          ),
        ),
      ),
      body: const Center(child: Text('自定义高度示例')),
    );
  }
}

案例8:带进度条的 AppBar

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: ProgressAppBar(),
    );
  }
}

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

  @override
  State<ProgressAppBar> createState() => _ProgressAppBarState();
}

class _ProgressAppBarState extends State<ProgressAppBar> {
  bool _isLoading = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('进度条示例'),
        actions: [
          IconButton(
            icon: const Icon(Icons.refresh),
            onPressed: () {
              setState(() {
                _isLoading = true;
              });
              Future.delayed(const Duration(seconds: 2), () {
                setState(() {
                  _isLoading = false;
                });
              });
            },
          ),
        ],
        bottom: _isLoading
            ? const PreferredSize(
                preferredSize: Size.fromHeight(4),
                child: LinearProgressIndicator(),
              )
            : null,
      ),
      body: const Center(child: Text('点击刷新按钮查看进度条')),
    );
  }
}

案例9:多行标题

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MultiLineTitlePage(),
    );
  }
}

class MultiLineTitlePage extends StatelessWidget {
  const MultiLineTitlePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              '主标题',
              style: TextStyle(fontSize: 18),
            ),
            Text(
              '副标题',
              style: TextStyle(fontSize: 12),
            ),
          ],
        ),
      ),
      body: const Center(child: Text('多行标题示例')),
    );
  }
}

案例10:自定义形状

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: CustomShapeAppBarPage(),
    );
  }
}

class CustomShapeAppBarPage extends StatelessWidget {
  const CustomShapeAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('自定义形状'),
        shape: const RoundedRectangleBorder(
          borderRadius: BorderRadius.vertical(
            bottom: Radius.circular(30),
          ),
        ),
      ),
      body: const Center(child: Text('自定义形状示例')),
    );
  }
}

完整示例

dart 复制代码
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: AppBarDemo(),
    );
  }
}

class AppBarDemo extends StatelessWidget {
  const AppBarDemo({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('AppBar 示例'),
        centerTitle: true,
        leading: IconButton(
          icon: const Icon(Icons.menu),
          onPressed: () {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('打开菜单')),
            );
          },
        ),
        actions: [
          IconButton(
            icon: const Icon(Icons.search),
            onPressed: () {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('搜索')),
              );
            },
          ),
          IconButton(
            icon: const Icon(Icons.notifications),
            onPressed: () {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('通知')),
              );
            },
          ),
          PopupMenuButton(
            itemBuilder: (context) => const [
              PopupMenuItem(
                value: 'settings',
                child: Text('设置'),
              ),
              PopupMenuItem(
                value: 'about',
                child: Text('关于'),
              ),
            ],
            onSelected: (value) {
              print('选择了: $value');
            },
          ),
        ],
      ),
      body: ListView(
        padding: const EdgeInsets.all(20),
        children: [
          ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const GradientAppBarPage(),
                ),
              );
            },
            child: const Text('渐变导航栏'),
          ),
          const SizedBox(height: 10),
          ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const TabBarPage(),
                ),
              );
            },
            child: const Text('TabBar 导航栏'),
          ),
          const SizedBox(height: 10),
          ElevatedButton(
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => const ScrollableAppBarPage(),
                ),
              );
            },
            child: const Text('可滚动导航栏'),
          ),
        ],
      ),
    );
  }
}

class GradientAppBarPage extends StatelessWidget {
  const GradientAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('渐变导航栏'),
        flexibleSpace: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.blue, Colors.purple],
            ),
          ),
        ),
      ),
      body: const Center(child: Text('渐变导航栏示例')),
    );
  }
}

class TabBarPage extends StatelessWidget {
  const TabBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('TabBar'),
          bottom: const TabBar(
            tabs: [
              Tab(text: '标签1'),
              Tab(text: '标签2'),
              Tab(text: '标签3'),
            ],
          ),
        ),
        body: const TabBarView(
          children: [
            Center(child: Text('页面 1')),
            Center(child: Text('页面 2')),
            Center(child: Text('页面 3')),
          ],
        ),
      ),
    );
  }
}

class ScrollableAppBarPage extends StatelessWidget {
  const ScrollableAppBarPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: [
          const SliverAppBar(
            expandedHeight: 200,
            pinned: true,
            flexibleSpace: FlexibleSpaceBar(
              title: Text('可滚动'),
              background: ColoredBox(
                color: Colors.blue,
              ),
            ),
          ),
          SliverList(
            delegate: SliverChildBuilderDelegate(
              (context, index) {
                return ListTile(title: Text('项目 $index'));
              },
              childCount: 50,
            ),
          ),
        ],
      ),
    );
  }
}

常见问题

1. 如何去除返回按钮?

dart 复制代码
AppBar(
  automaticallyImplyLeading: false,  // 不自动显示返回按钮
  title: Text('标题'),
)

2. 如何自定义返回按钮?

dart 复制代码
AppBar(
  leading: IconButton(
    icon: Icon(Icons.arrow_back),
    onPressed: () {
      Navigator.pop(context);
    },
  ),
  title: Text('标题'),
)

3. 如何去除阴影?

dart 复制代码
AppBar(
  title: Text('标题'),
  elevation: 0,  // 无阴影
)

4. 如何让内容延伸到 AppBar 下方?

dart 复制代码
Scaffold(
  extendBodyBehindAppBar: true,
  appBar: AppBar(
    backgroundColor: Colors.transparent,
    elevation: 0,
  ),
  body: Container(),
)

属性速查表

属性 说明
title 标题
leading 左侧组件
actions 右侧操作按钮
backgroundColor 背景颜色
centerTitle 标题是否居中
elevation 阴影高度
bottom 底部组件
flexibleSpace 灵活空间
toolbarHeight 工具栏高度
shape 形状

总结

AppBar 的核心要点:

  1. 显示页面标题和操作按钮
  2. leading 设置左侧组件
  3. actions 设置右侧按钮
  4. bottom 可以放 TabBar
  5. flexibleSpace 可以自定义背景

记住:

  • AppBar 通常放在 Scaffold 的 appBar 属性中
  • centerTitle 控制标题居中
  • elevation 控制阴影
  • 可以使用 SliverAppBar 实现滚动效果

AppBar 是应用的门面,设计好它能提升用户体验!

相关推荐
摘星编程2 小时前
React Native for OpenHarmony 实战:Localization 本地化详解
javascript·react native·react.js
鸣弦artha2 小时前
Flutter框架跨平台鸿蒙开发——Flutter Framework层架构概览
flutter·架构·harmonyos
Amumu121382 小时前
React扩展(一)
前端·javascript·react.js
cypking2 小时前
三、前端规范化 项目代码规范
前端·代码规范
xkxnq2 小时前
第二阶段:Vue 组件化开发(第 28天)
前端·javascript·vue.js
摘星编程3 小时前
React Native for OpenHarmony 实战:RTL 从右到左布局详解
javascript·react native·react.js
Yvonne爱编码3 小时前
前端工程化进阶:从搭建完整项目脚手架到性能优化【技术类】
前端·状态模式
cypking3 小时前
二、前端规范化 遇到的问题及解决方案
前端
小范馆3 小时前
STM32F03C8T6通过AT指令获取天气API
前端·javascript·stm32