什么是 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 的核心要点:
- 显示页面标题和操作按钮
- leading 设置左侧组件
- actions 设置右侧按钮
- bottom 可以放 TabBar
- flexibleSpace 可以自定义背景
记住:
- AppBar 通常放在 Scaffold 的 appBar 属性中
- centerTitle 控制标题居中
- elevation 控制阴影
- 可以使用 SliverAppBar 实现滚动效果
AppBar 是应用的门面,设计好它能提升用户体验!