开篇寄语
伯衡君发现总结了有关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!")), ); } }
效果如下图所示:
- 我的微信
- 微信扫一扫加好友
- 我的微信公众号
- 扫描关注公众号