
开篇寄语
伯衡君发现总结了有关flutter编程语言以制作全平台的App,经过前面三篇分段式总结,似乎已经可以逐渐创建简单的App了,事实也恰恰如此,不过,要想制作更加精美的App,功能更加强大的App,还需要继续精深学习,这次学习的内容则是AppBar,也就是应用的最上方那部分,添加各种功能,特效,美化之类的,让我们开始吧。
前情提要
- 《Flutter制作自己的第一个全平台APP学习之Widgets篇》
- 《Flutter制作自己的第一个全平台APP学习之Layouts篇》
- 《Flutter制作自己的第一个全平台APP学习之Lists篇》
内容详情
以下内容大多是更改lib下的main.dart文件内容,删掉里面的内容,复制粘贴代码,开启调试就可以出现了。
Basic
- 简单的样式,格式等,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// Remove the debug banner
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.redAccent,
leading: const Icon(Icons.tag_faces),
title: const Text("Menu"),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.directions_bike),
onPressed: () {},
),
IconButton(
icon: const Icon(Icons.directions_bus),
onPressed: () {},
),
PopupMenuButton(
itemBuilder: (BuildContext context) {
return [
const PopupMenuItem(child: Text('Boat')),
const PopupMenuItem(child: Text('Train'))
];
},
)
],
),
body: const Center(
child: Text(
"Hello World",
)),
);
}
}
生成效果如下图所示:

SliverAppBar
- 可以简单理解为大块的顶部空间,试举例如下:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'HomePage',
theme: ThemeData(primaryColor: Colors.purple),
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
SliverAppBar showSliverAppBar(String screenTitle) {
return SliverAppBar(
backgroundColor: Colors.purple,
floating: true,
pinned: true,
snap: false,
title: Text(screenTitle),
bottom: TabBar(
tabs: [
Tab(
icon: Icon(Icons.home),
text: 'Home',
),
Tab(
icon: Icon(Icons.settings),
text: 'Setting',
)
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: DefaultTabController(
length: 2,
child: TabBarView(children: [
// This CustomScrollView display the Home tab content
CustomScrollView(
slivers: [
showSliverAppBar('HomePage'),
// Anther sliver widget: SliverList
SliverList(
delegate: SliverChildListDelegate([
Container(
height: 200,
child: Center(
child: Text(
'Home Tab',
style: TextStyle(fontSize: 40),
),
),
),
Container(
height: 1500,
color: Colors.green,
),
]),
),
],
),
// This shows the Settings tab content
CustomScrollView(
slivers: [
showSliverAppBar('Settings Screen'),
// Show other sliver stuff
SliverList(
delegate: SliverChildListDelegate([
Container(
height: 600,
color: Colors.blue[200],
child: Center(
child: Text(
'Settings Tab',
style: TextStyle(fontSize: 40),
),
),
),
Container(
height: 1200,
color: Colors.pink,
),
]),
),
],
)
]),
));
}
}
效果如下图所示:

Bottom AppBar & floatingActionButton
- 就是底部的选择菜单啦,一般是四个或者五个按钮,一般都与一个悬浮按钮一起出现,试举例如下:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
theme: _buildShrineTheme(),
);
}
}
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
IconButton(icon: Icon(Icons.menu), onPressed: () {}),
Spacer(),
IconButton(icon: Icon(Icons.search), onPressed: () {}),
IconButton(icon: Icon(Icons.hearing), onPressed: () {}),
IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
],
),
),
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
ThemeData _buildShrineTheme() {
final ThemeData base = ThemeData.light();
return base.copyWith(
colorScheme: _shrineColorScheme,
textTheme: _buildShrineTextTheme(base.textTheme),
);
}
TextTheme _buildShrineTextTheme(TextTheme base) {
return base
.copyWith(
caption: base.caption!.copyWith(
fontWeight: FontWeight.w400,
fontSize: 14,
letterSpacing: defaultLetterSpacing,
),
button: base.button!.copyWith(
fontWeight: FontWeight.w500,
fontSize: 14,
letterSpacing: defaultLetterSpacing,
),
)
.apply(
fontFamily: 'Rubik',
displayColor: shrineBrown900,
bodyColor: shrineBrown900,
);
}
const ColorScheme _shrineColorScheme = ColorScheme(
primary: shrinePink100,
primaryVariant: shrineBrown900,
secondary: shrinePink50,
secondaryVariant: shrineBrown900,
surface: shrineSurfaceWhite,
background: shrineBackgroundWhite,
error: shrineErrorRed,
onPrimary: shrineBrown900,
onSecondary: shrineBrown900,
onSurface: shrineBrown900,
onBackground: shrineBrown900,
onError: shrineSurfaceWhite,
brightness: Brightness.light,
);
const Color shrinePink50 = Color(0xFFFEEAE6);
const Color shrinePink100 = Color(0xFFFEDBD0);
const Color shrinePink300 = Color(0xFFFBB8AC);
const Color shrinePink400 = Color(0xFFEAA4A4);
const Color shrineBrown900 = Color(0xFF442B2D);
const Color shrineBrown600 = Color(0xFF7D4F52);
const Color shrineErrorRed = Color(0xFFC5032B);
const Color shrineSurfaceWhite = Color(0xFFFFFBFA);
const Color shrineBackgroundWhite = Colors.white;
const defaultLetterSpacing = 0.03;
效果如下图所示:

另一种展现形式,如下代码所示:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key);
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
static const TextStyle optionStyle =
TextStyle(fontSize: 30, fontWeight: FontWeight.bold);
static const List<Widget> _widgetOptions = <Widget>[
Text(
'Index 0: Home',
style: optionStyle,
),
Text(
'Index 1: Business',
style: optionStyle,
),
Text(
'Index 2: School',
style: optionStyle,
),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BottomNavigationBar Sample'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Business',
),
BottomNavigationBarItem(
icon: Icon(Icons.school),
label: 'School',
),
],
currentIndex: _selectedIndex,
selectedItemColor: Colors.amber[800],
onTap: _onItemTapped,
),
);
}
}
效果如下图所示:

Backdrop
- 这个在flutter的官方库是没有的,需要调用第三方的库,非常简单,但是异形样式还是很前卫的,试举例如下:
import 'package:flutter/material.dart';
import 'package:backdrop/backdrop.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Backdrop Demo',
home: BackdropScaffold(
appBar: BackdropAppBar(
title: Text("Backdrop Example"),
actions: <Widget>[
BackdropToggleButton(
icon: AnimatedIcons.list_view,
)
],
),
backLayer: Center(
child: Text("Back Layer"),
),
subHeader: BackdropSubHeader(
title: Text("Sub Header"),
),
frontLayer: Center(
child: Text("Front Layer"),
),
),
);
}
}
效果如下图所示:

Convex Appbar
- 这个是Bottom AppBar & floatingActionButton的升级版,虽然不是flutter的官方库,但是第三方库中最为流行之一,试举一例:
import 'package:flutter/material.dart';
import 'package:convex_bottom_bar/convex_bottom_bar.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Backdrop Demo',
home: Scaffold(
bottomNavigationBar: ConvexAppBar(
items: [
TabItem(icon: Icons.home, title: 'Home'),
TabItem(icon: Icons.map, title: 'Discovery'),
TabItem(icon: Icons.add, title: 'Add'),
TabItem(icon: Icons.message, title: 'Message'),
TabItem(icon: Icons.people, title: 'Profile'),
],
initialActiveIndex: 2, //optional, default as 0
onTap: (int i) => print('click index=$i'),
)));
}
}
效果如下图所示:

search bar
- 搜索框,一般应用中都很常见,flutter的一个第三方库名为flutter_search_bar非常好用,故以此为例,代码如下:
import 'package:flutter/material.dart';
import 'package:flutter_search_bar/flutter_search_bar.dart';
void main() {
runApp(new SearchBarDemoApp());
}
class SearchBarDemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Search Bar Demo',
theme: new ThemeData(primarySwatch: Colors.blue),
home: new SearchBarDemoHome());
}
}
class SearchBarDemoHome extends StatefulWidget {
@override
_SearchBarDemoHomeState createState() => new _SearchBarDemoHomeState();
}
class _SearchBarDemoHomeState extends State<SearchBarDemoHome> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
late SearchBar searchBar;
AppBar buildAppBar(BuildContext context) {
return new AppBar(
title: new Text('Search Bar Demo'),
actions: [searchBar.getSearchAction(context)]);
}
void onSubmitted(String value) {
setState(() {
var context = _scaffoldKey.currentContext;
if (context == null) {
return;
}
ScaffoldMessenger.maybeOf(context)?.showSnackBar(
new SnackBar(content: new Text('You wrote "$value"!')));
});
}
_SearchBarDemoHomeState() {
searchBar = new SearchBar(
inBar: false,
buildDefaultAppBar: buildAppBar,
setState: setState,
onSubmitted: onSubmitted,
onCleared: () {
print("Search bar has been cleared");
},
onClosed: () {
print("Search bar has been closed");
});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: searchBar.build(context),
key: _scaffoldKey,
body: new Center(
child: new Text("Don't look at me! Press the search button!")),
);
}
}
效果如下图所示:

- 我的微信
- 微信扫一扫加好友
-
- 我的微信公众号
- 扫描关注公众号
-





