内容简介:这里我们先看看需要注意的几点当通过
- Flutter和Dart系列文章 和 代码GitHub地址
-
Flutter
一切皆Widget
的核心思想, 为我们提供了两种主题风格 -
CupertinoApp
: 一个封装了很多iOS
风格的小部件,一般作为顶层widget
使用 -
MaterialApp
: 一个封装了很多安卓风格的小部件,一般作为顶层widget
使用, 下面我们先看下这个Widget
MaterialApp
这里我们先看看 MaterialApp
的构造函数和相关函数
const MaterialApp({ Key key, // 导航主键, GlobalKey<NavigatorState> this.navigatorKey, // 主页, Widget this.home, // 路由 this.routes = const <String, WidgetBuilder>{}, // 初始化路由, String this.initialRoute, // 构造路由, RouteFactory this.onGenerateRoute, // 为止路由, RouteFactory this.onUnknownRoute, // 导航观察器 this.navigatorObservers = const <NavigatorObserver>[], // widget的构建 this.builder, // APP的名字 this.title = '', // GenerateAppTitle, 每次在WidgetsApp构建时都会重新生成 this.onGenerateTitle, // 背景颜色 this.color, // 主题, ThemeData this.theme, // app语言支持, Locale this.locale, // 多语言代理, Iterable<LocalizationsDelegate<dynamic>> this.localizationsDelegates, // flutter.widgets.widgetsApp.localeListResolutionCallback this.localeListResolutionCallback, // flutter.widgets.widgetsApp.localeResolutionCallback this.localeResolutionCallback, // 支持的多语言, Iterable<Locale> this.supportedLocales = const <Locale>[Locale('en', 'US')], // 是否显示网格 this.debugShowMaterialGrid = false, // 是否打开性能监控,覆盖在屏幕最上面 this.showPerformanceOverlay = false, // 是否打开栅格缓存图像的检查板 this.checkerboardRasterCacheImages = false, // 是否打开显示到屏幕外位图的图层的检查面板 this.checkerboardOffscreenLayers = false, // 是否打开覆盖图,显示框架报告的可访问性信息 显示边框 this.showSemanticsDebugger = false, // 是否显示右上角的Debug标签 this.debugShowCheckedModeBanner = true, }) 复制代码
需要注意的几点
- 如果
home
首页指定了,routes
里面就不能有'/'
的根路由了,会报错,/
指定的根路由就多余了 - 如果没有
home
指定具体的页面,那routes
里面就有/
来指定根路由 - 路由的顺序按照下面的规则来:
- 1、如果有
home
,就会从home
进入 - 2、如果没有
home
,有routes
,并且routes
指定了入口'/'
,就会从routes
的/
进入 - 3、如果上面两个都没有,或者路由达不到,如果有
onGenerateRoute
,就会进入生成的路由 - 4、如果连上面的生成路由也没有,就会走到
onUnknownRoute
,不明所以的路由,比如网络连接失败,可以进入断网的页面
- 1、如果有
routes
- 声明程序中有哪个通过
Navigation.of(context).pushNamed
跳转的路由 - 参数以键值对的形式传递
-
key
:路由名字 -
value
:对应的Widget
-
routes: { '/home': (BuildContext content) => Home(), '/mine': (BuildContext content) => Mine(), }, 复制代码
initialRoute
- 初始化路由, 当用户进入程序时,自动打开对应的路由(home还是位于一级)
- 传入的是上面
routes
的key
, 跳转的是对应的Widget
(如果该Widget
有Scaffold.AppBar
,并不做任何修改,左上角有返回键)
routes: { '/home': (BuildContext content) => Home(), '/mine': (BuildContext content) => Mine(), }, initialRoute: '/mine', 复制代码
onGenerateRoute
当通过 Navigation.of(context).pushNamed
跳转路由时, 在 routes
查找不到时,会调用该方法
onGenerateRoute: (RouteSettings setting) { return MaterialPageRoute( settings: setting, builder: (BuildContext content) => Text('生成一个路由') ); }, 复制代码
onUnknownRoute
未知路由, 效果跟 onGenerateRoute
一样, 在未设置 onGenerateRoute
的情况下, 才会去调用 onUnknownRoute
onUnknownRoute: (RouteSettings setting) { return MaterialPageRoute( settings: setting, builder: (BuildContext content) => Text('这是一个未知路由') ); }, 复制代码
navigatorObservers
- 路由观察器,当调用
Navigator
的相关方法时,会回调相关的操作 - 比如
push
,pop
,remove
,replace
是可以拿到当前路由和后面路由的信息 - 获取路由的名字:
route.settings.name
// navigatorObservers: [HomeObserver()], // 继承NavigatorObserver class HomeObserver extends NavigatorObserver { @override void didPush(Route route, Route previousRoute) { super.didPush(route, previousRoute); // 获取路由的名字 print('name = ${route.settings.name}'); // 获取返回的内容 print('reaule = ${route.currentResult}'); } } 复制代码
builder
如果设置了这个参数, 那么将会优先渲染这个 builder
, 而不会在走路由
builder: (BuildContext content, Widget widget) => Text('builder'), 复制代码
title
- 设备用于识别用户的应用程序的单行描述
- 在
Android
上,标题显示在任务管理器的应用程序快照上方,当用户按下“最近的应用程序”按钮时会显示这些快照 - 在
iOS
上,无法使用此值。来自应用程序的Info.plist
的CFBundleDisplayName
在任何时候都会被引用,否则就会引用CFBundleName
- 要提供初始化的标题,可以用
onGenerateTitle
CupertinoApp
用于创建 iOS
风格应用的顶层组件, 相关属性和 MaterialApp
相比只是少了 theme
和 debugShowMaterialGrid
, 其他属性都一样, 如下所示
const CupertinoApp({ Key key, this.navigatorKey, this.home, this.routes = const <String, WidgetBuilder>{}, this.initialRoute, this.onGenerateRoute, this.onUnknownRoute, this.navigatorObservers = const <NavigatorObserver>[], this.builder, this.title = '', this.onGenerateTitle, this.color, this.locale, this.localizationsDelegates, this.localeListResolutionCallback, this.localeResolutionCallback, this.supportedLocales = const <Locale>[Locale('en', 'US')], this.showPerformanceOverlay = false, this.checkerboardRasterCacheImages = false, this.checkerboardOffscreenLayers = false, this.showSemanticsDebugger = false, this.debugShowCheckedModeBanner = true, }) 复制代码
使用示例如下
return CupertinoApp( title: 'Cupertino App', color: Colors.red, home: CupertinoPageScaffold( backgroundColor: Colors.yellow, resizeToAvoidBottomInset: true, navigationBar: CupertinoNavigationBar( middle: Text('Cupertino App Bar'), backgroundColor: Colors.blue, ), child: Center( child: Container( child: Text('Hello World'), ), ), ), ); 复制代码
CupertinoPageScaffold
一个 iOS
风格的页面的基本布局结构。包含内容和导航栏
const CupertinoPageScaffold({ Key key, // 设置导航栏, 后面会详解 this.navigationBar, // 设置内容页面的背景色 this.backgroundColor = CupertinoColors.white, // 子widget是否应该自动调整自身大小以适应底部安全距离 this.resizeToAvoidBottomInset = true, @required this.child, }) 复制代码
navigationBar
const CupertinoNavigationBar({ Key key, //导航栏左侧组件 this.leading, //是否显示左边组件, 好像无效 this.automaticallyImplyLeading = true, //是否显示中间组件, 好像无效 this.automaticallyImplyMiddle = true, //导航栏左侧组件的右边的文本, 好像无效 this.previousPageTitle, // 导航栏中间组件 this.middle, // 导航栏右侧组件 this.backgroundColor = _kDefaultNavBarBackgroundColor, // 设置左右组件的内边距, EdgeInsetsDirectional this.padding, //左侧默认组件和左侧组件右边文本的颜色 this.actionsForegroundColor = CupertinoColors.activeBlue, this.transitionBetweenRoutes = true, this.heroTag = _defaultHeroTag, }) 复制代码
使用示例
return CupertinoApp( title: 'Cupertino App', color: Colors.red, debugShowCheckedModeBanner: false, home: CupertinoPageScaffold( backgroundColor: Colors.yellow, resizeToAvoidBottomInset: true, navigationBar: CupertinoNavigationBar( leading: Icon(Icons.person), automaticallyImplyLeading: false, automaticallyImplyMiddle: false, previousPageTitle: '返回', middle: Text('Cupertino App Bar'), trailing: Icon(Icons.money_off), border: Border.all(), backgroundColor: Colors.white, padding: EdgeInsetsDirectional.fromSTEB(10, 10, 10, 10), actionsForegroundColor: Colors.red, transitionBetweenRoutes: false, heroTag: Text('data'), ), child: Center( child: Container( child: Text('Hello World'), ), ), ), ); 复制代码
Scaffold
-
Scaffold
通常被用作MaterialApp
的子Widget
(安卓风格),它会填充可用空间,占据整个窗口或设备屏幕 -
Scaffold
提供了大多数应用程序都应该具备的功能,例如顶部的appBar
,底部的bottomNavigationBar
,隐藏的侧边栏drawer
等
const Scaffold({ Key key, // 显示在界面顶部的一个AppBar this.appBar, // 当前界面所显示的主要内容Widget this.body, // 悬浮按钮, 默认在右下角位置显示 this.floatingActionButton, // 设置悬浮按钮的位置 this.floatingActionButtonLocation, // 悬浮按钮出现消失的动画 this.floatingActionButtonAnimator, // 在底部呈现一组button,显示于[bottomNavigationBar]之上,[body]之下 this.persistentFooterButtons, // 一个垂直面板,显示于左侧,初始处于隐藏状态 this.drawer, // 一个垂直面板,显示于右侧,初始处于隐藏状态 this.endDrawer, // 出现于底部的一系列水平按钮 this.bottomNavigationBar, // 底部的持久化提示框 this.bottomSheet, // 背景色 this.backgroundColor, // 重新计算布局空间大小 this.resizeToAvoidBottomPadding = true, // 是否显示到底部, 默认为true将显示到顶部状态栏 this.primary = true, }) 复制代码
appBar
设置导航栏, 接受一个抽象类 PreferredSizeWidget
, 这里使用其子类 AppBar
进行设置, 后面会详解
floatingActionButton
- 设置一个悬浮按钮, 默认在右下角位置显示, 这里使用
FloatingActionButton
设置 -
FloatingActionButton
是Material
设计规范中的一种特殊Button
,通常悬浮在页面的某一个位置作为某种常用动作的快捷入口, 后面会详解
floatingActionButtonLocation
设置悬浮按钮的位置, 接受一个抽象类 FloatingActionButtonLocation
// 右下角, 距离底部有一点距离, 默认值 static const FloatingActionButtonLocation endFloat = _EndFloatFabLocation(); // 中下方, 距离底部有一点距离 static const FloatingActionButtonLocation centerFloat = _CenterFloatFabLocation(); // 右下角, 距离底部没有间距 static const FloatingActionButtonLocation endDocked = _EndDockedFloatingActionButtonLocation(); // 中下方, 距离底部没有间距 static const FloatingActionButtonLocation centerDocked = _CenterDockedFloatingActionButtonLocation(); 复制代码
FloatingActionButton
在 Material Design
中,一般用来处理界面中最常用,最基础的用户动作。它一般出现在屏幕内容的前面,通常是一个圆形,中间有一个图标, 有以下几种构造函数
const FloatingActionButton({ Key key, this.child, // 文字解释, 按钮呗长按时显示 this.tooltip, // 前景色 this.foregroundColor, // 背景色 this.backgroundColor, // hero效果使用的tag,系统默认会给所有FAB使用同一个tag,方便做动画效果 this.heroTag = const _DefaultHeroTag(), // 未点击时阴影值,默认6.0 this.elevation = 6.0, // 点击时阴影值,默认12.0 this.highlightElevation = 12.0, // 点击事件监听 @required this.onPressed, // 是否为“mini”类型,默认为false this.mini = false, // 设置阴影, 设置shape时,默认的elevation将会失效,默认为CircleBorder this.shape = const CircleBorder(), // 剪切样式 this.clipBehavior = Clip.none, // 设置点击区域大小的样式, MaterialTapTargetSize的枚举值 this.materialTapTargetSize, // 是否为”extended”类型 this.isExtended = false, }) 复制代码
mini
- 是否为
mini
类型,默认为false
-
FloatingActionButton
分为三种类型:regular
,mini
,extended
-
regular
和mini
两种类型通过默认的构造方法实现, 只有图片 - 大小限制如下
const BoxConstraints _kSizeConstraints = const BoxConstraints.tightFor( width: 56.0, height: 56.0, ); const BoxConstraints _kMiniSizeConstraints = const BoxConstraints.tightFor( width: 40.0, height: 40.0, ); const BoxConstraints _kExtendedSizeConstraints = const BoxConstraints( minHeight: 48.0, maxHeight: 48.0, ); 复制代码
isExtended
- 是否为
extended
类型, 设置为true
即可 - 除此之外, 还可以使用
extended
构造函数创建该类型
FloatingActionButton.extended({ Key key, this.tooltip, this.foregroundColor, this.backgroundColor, this.heroTag = const _DefaultHeroTag(), this.elevation = 6.0, this.highlightElevation = 12.0, @required this.onPressed, this.shape = const StadiumBorder(), this.isExtended = true, this.materialTapTargetSize, this.clipBehavior = Clip.none, // 设置图片 @required Widget icon, // 设置文字 @required Widget label, }) 复制代码
从参数上看差异并不大,只是把默认构造方法中的 child
换成了 icon
和 label
,不过通过下面的代码可以看到,传入的 label
和 icon
也是用来构建 child
的,不过使用的是 Row
来做一层包装而已
AppBar
AppBar
是一个 Material
风格的导航栏,它可以设置标题、导航栏菜单、底部 Tab
等
AppBar({ Key key, // 导航栏左侧weidget this.leading, // 如果leading为null,是否自动实现默认的leading按钮 this.automaticallyImplyLeading = true, // 导航栏标题 this.title, // 导航栏右侧按钮, 接受一个数组 this.actions, // 一个显示在AppBar下方的控件,高度和AppBar高度一样,可以实现一些特殊的效果,该属性通常在SliverAppBar中使用 this.flexibleSpace, // 一个AppBarBottomWidget对象, 设置TabBar this.bottom, //中控件的z坐标顺序,默认值为4,对于可滚动的SliverAppBar,当 SliverAppBar和内容同级的时候,该值为0,当内容滚动 SliverAppBar 变为 Toolbar 的时候,修改elevation的值 this.elevation = 4.0, // 背景颜色,默认值为 ThemeData.primaryColor。改值通常和下面的三个属性一起使用 this.backgroundColor, // 状态栏的颜色, 黑白两种, 取值: Brightness.dark this.brightness, // 设置导航栏上图标的颜色、透明度、和尺寸信息 this.iconTheme, // 设置导航栏上文字样式 this.textTheme, // 导航栏的内容是否显示在顶部, 状态栏的下面 this.primary = true, // 标题是否居中显示,默认值根据不同的操作系统,显示方式不一样 this.centerTitle, // 标题间距,如果希望title占用所有可用空间,请将此值设置为0.0 this.titleSpacing = NavigationToolbar.kMiddleSpacing, // 应用栏的 工具 栏部分透明度 this.toolbarOpacity = 1.0, // 底部导航栏的透明度设置 this.bottomOpacity = 1.0, }) 复制代码
leading
导航栏左侧 weidget
final Widget leading; // 示例 leading: Icon(Icons.home), 复制代码
actions
导航栏右侧按钮, 接受一个数组
final List<Widget> actions; // 示例 actions: <Widget>[ Icon(Icons.add), Icon(Icons.home), ], 复制代码
brightness
状态栏的颜色, 黑白两种
// 状态栏白色 brightness: Brightness.dark, // 状态栏黑色 brightness: Brightness.light, 复制代码
iconTheme
设置导航栏上图标的颜色、透明度、和尺寸信息
const IconThemeData({this.color, double opacity, this.size}) // 示例 iconTheme: IconThemeData(color: Colors.white, opacity: 0.56, size: 30), 复制代码
TabBar
- 在
AppBar
中通过bottom
属性来添加一个导航栏底部tab
按钮组, 接受一个PreferredSizeWidget
类型 -
PreferredSizeWidget
是一个抽象类, 这里我们使用TabBar
class TabBar extends StatefulWidget implements PreferredSizeWidget { const TabBar({ Key key, // 数组,显示的标签内容,一般使用Tab对象,当然也可以是其他的Widget @required this.tabs, // TabController对象 this.controller, // 是否可滚动 this.isScrollable = false, // 指示器颜色 this.indicatorColor, // 指示器高度 this.indicatorWeight = 2.0, // 指示器内边距 this.indicatorPadding = EdgeInsets.zero, // 设置选中的样式decoration,例如边框等 this.indicator, // 指示器大小, 枚举值TabBarIndicatorSize this.indicatorSize, // 选中文字颜色 this.labelColor, // 选中文字样式 this.labelStyle, // 文字内边距 this.labelPadding, // 未选中文字颜色 this.unselectedLabelColor, // 未选中文字样式 this.unselectedLabelStyle, }) } // Tab的构造函数 const Tab({ Key key, // 文本 this.text, // 图标 this.icon, // 子widget this.child, }) 复制代码
效果如下
相关代码如下
void main(List<String> args) => runApp(NewApp()); class NewApp extends StatefulWidget { @override State<StatefulWidget> createState() { // TODO: implement createState return App(); } } class App extends State<NewApp> with SingleTickerProviderStateMixin { List tabs = ['语文', '数学', '英语', '政治', '历史', '地理', '物理', '化学', '生物']; TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(initialIndex: 0, length: tabs.length, vsync: this); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('CoderTitan'), backgroundColor: Colors.blueAccent, brightness: Brightness.dark, centerTitle: true, bottom: TabBar( controller: _tabController, tabs: tabs.map((e) => Tab(text: e)).toList(), isScrollable: true, indicatorColor: Colors.red, indicatorWeight: 2, indicatorSize: TabBarIndicatorSize.label, labelColor: Colors.orange, unselectedLabelColor: Colors.white, labelStyle: TextStyle(fontSize: 18, color: Colors.orange), unselectedLabelStyle: TextStyle(fontSize: 15, color: Colors.white), ), ), body: TabBarView( controller: _tabController, children: tabs.map((e) { return Container( alignment: Alignment.center, child: Text(e, style:TextStyle(fontSize: 50)), ); }).toList(), ), ), debugShowCheckedModeBanner: false, ); } } 复制代码
BottomNavigationBar
- 在
Scaffold
中有一个属性bottomNavigationBar
用于设置最底部的tabbar
导航栏 - 使用
Material
组件库提供的BottomNavigationBar
和BottomNavigationBarItem
两个Widget
来实现Material风格的底部导航栏
BottomNavigationBar({ Key key, // 子widget数组 @required this.items, // 每一个item的点击事件 this.onTap, // 当前选中的索引 this.currentIndex = 0, // 类型 BottomNavigationBarType type, // 文字颜色 this.fixedColor, // 图片大小 this.iconSize = 24.0, }) 复制代码
items
包含所有子 Widget
的数组
final List<BottomNavigationBarItem> items; const BottomNavigationBarItem({ // 未选中图片 @required this.icon, // 标题 this.title, // 选中的图片 Widget activeIcon, // 背景色 this.backgroundColor, }) 复制代码
以上所述就是小编给大家介绍的《Flutter中App的主题和导航》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ajax Design Patterns
Michael Mahemoff / O'Reilly Media / 2006-06-29 / USD 44.99
Ajax, or Asynchronous JavaScript and XML, exploded onto the scene in the spring of 2005 and remains the hottest story among web developers. With its rich combination of technologies, Ajax provides a s......一起来看看 《Ajax Design Patterns》 这本书的介绍吧!