PHP开源Hub
致力于开发者的提升

Flutter 基础(五)Material 组件之 MaterialApp、Scaffold、AppBar

Flutter基础(五)Material组件之MaterialApp、Scaffold、AppBar

前言

在上一篇文章 Flutter 基础(四)开发 Flutter 应用前需要掌握的 Basics Widget,我们学习了 Basics Widget,除了 Basics Widget,我们还需要了解 Material Components,也就是 Material 组件。它提供了实现 Material Design 准则的视觉、行为和动作的 Widget。
官方将 Material 组件分为为几个类型:

  • 应用程序结构和导航
  • Button
  • 输入和选择
  • 对话框,警告弹框和面板
  • 信息显示
  • 布局

主要介绍应用程序结构和导航,会分为两篇文章进行介绍,这一篇介绍应用程序结构和导航分类中的 MaterialApp、Scaffold、AppBar。

1.MaterialApp

说到 Material 组件,不得不提到 MaterialApp,它包含了许多 Widget,这些 Widget 通常是实现 Material Design 的应用程序所必需的。
MaterialApp 在此前的文章都用过,简单的使用这里就不介绍了,这里主要介绍下路由。
移动 App 中通常通过全屏元素 “屏幕” 或 “页面” 来显示内容。在 Flutter 中,这些元素被称为 route(路由),它们由 Navigator 管理。Navigator 不仅管理了一堆 route,还提供管理堆栈的方法 Navigator.push 和 Navigator.pop,通过路由对象的进出栈来控制页面的跳转。

flutter 路由的使用方式主要有两种,一种是新建路由,一种是注册路由。我们分别用这两种方式写例子:
首屏是第一个界面,通过第一个界面的按钮跳转到第二页,点击第二页的按钮回到第一页。

1.1 新建路由


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 title: 'Material Components',
 home: FirstPage(),
 );
 }
}

class FirstPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('第一页'),
 ),
 body: Padding(
 padding: EdgeInsets.all(30.0),
 child: RaisedButton(
 child:  Text('跳转到第二页'),
 onPressed: () {
 Navigator.push(//1
 context,
 MaterialPageRoute(builder: (context) => SecondPage()),
 );
 },
 ),
 ),
 );
 }
}

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('第二页'),
 ),
 body: Padding(
 padding: EdgeInsets.all(30.0),
 child: RaisedButton(
 child: Text('回到上一页'),
 onPressed: () {
 Navigator.pop(context);//2
 }),
 ),
 );
 }
}

注释 1 处调用了 Navigator.push,将新建的路由添加到 Navigator 管理的 route 堆栈的栈顶,这个路由我们可以自定义,但是建议使用 MaterialPageRoute,它是一个模态路由,可以自适应各个平台进行页面替换,并提供了相应的页面切换动画。在 Android 平台时,页面进入动画是向上滑动并淡出,退出是相反的动画,如果是在 iOS 平台 ,页面进入动画是从右侧滑入,退出是相反的动画。
点击’跳转到第二页’按钮时会跳转到 SecondPage。注释 2 处的 Navigator.pop 用于弹出 route 堆栈最顶层的 Route。效果如下两个图所示。

1.2 注册路由


import 'package:flutter/material.dart';
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 title: 'Material Components',
 home: FirstPage(),
 routes:  <String, WidgetBuilder>{//1
 '/first': (BuildContext context) => FirstPage(),
 '/second': (BuildContext context) => SecondPage(),
 },
 initialRoute: '/first' ,
 );
 }
}

class FirstPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('第一页'),
 ),
 body: Padding(
 padding: EdgeInsets.all(30.0),
 child: RaisedButton(
 child: Text('跳转到第二页'),
 onPressed: () {
 Navigator.pushNamed(context, '/second');//2
 },
 ),
 ),
 );
 }
}

class SecondPage extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('第二页'),
 ),
 body: Padding(
 padding: EdgeInsets.all(30.0),
 child: RaisedButton(
 child: Text('回到上一页'),
 onPressed: () {
 Navigator.of(context).pop();
 }),
 ),
 );
 }
}

通过注释 1 处的 routes 用于初始化一个路由列表,当推送路由时,将在 routes 中查找路径名称,如果名称存在,则关联的 WidgetBuilder 用于构造 MaterialPageRoute。注释 2 处的 Navigator.pushNamed 和 Navigator.push 作用类似,只不过 pushNamed 的参数为路由的名称。

2. Scaffold

Scaffold 同样属于 Material 组件,它实现了 Material Design 的基本布局结构,因此它经常会作为 MaterialApp 的子 Widget, Scaffold 会自动填充可用的空间,这通常意味着它将占据整个窗口或屏幕,并且 Scaffold 会自动适配屏幕。我们的布局就是在 Scaffold 中进行编写的。


import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
 // This widget is the root of your application.
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 home: Scaffold(
 appBar: AppBar(
 title: Text('Scaffold示例'),
 ),
 body: Padding(
 padding: EdgeInsets.all(30.0),
 child: Text('Scaffold'),
 ),
 bottomNavigationBar: BottomAppBar(
 child: Container(height: 50),
 ),
 drawer: Drawer(
 child: Center(
 child: Text('抽屉'),
 ),
 ),
 floatingActionButton: FloatingActionButton(
 child: Icon(Icons.add),
 ),
 ),
 );
 }
}

Scaffold 的属性有很多,例子中用了几个属性:

  • appBar:用于设置顶部的标题栏。
  • body:显示 Scaffold 的主要内容。
  • bottomNavigationBar:用于设置 Scaffold 的底部导航栏,
  • drawer:用于设置抽屉效果。
  • floatingActionButton:用于设置位于右下角的按钮。

效果如下所示:

可以看到在 AppBar 上有个抽屉的按钮,点击按钮就会滑出抽屉。

3. AppBar

AppBar 由 toolbar 和其他的可选 Widget 组成,比如 TabBar 和 FlexibleSpaceBar。
AppBar 会在顶部显示 leading、title、actions 等内容,底部 bottom 通常显示 TabBar,下图展示了这些内容的位置分布。


import 'package:flutter/material.dart';

void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return MaterialApp(
 home: MyScaffld(),
 );
 }
}

class MyScaffld extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
 return Scaffold(
 appBar: AppBar(
 title: Text('AppBar示例'),
 leading: FlutterLogo(colors: Colors.lightGreen),
 actions: <Widget>[
 IconButton(
 icon: Icon(Icons.share),
 onPressed: () {
 print('添加按钮');
 },
 ),
 ],
 ),
 );
 }
}

这次没有把所有代码写在 MyApp 类中,而是将 Scaffld 的定义放在了 MyScaffld 类中。

上面代码的 Widget 树如下所示,遵守 Material Design 准则的 flutter 应用的 Widget 树大致也是如此。

总结

本文总结了 Material 组件中的三种 Widget,可以说它们是使用 Material 组件时最常使用的 Widget,常用到我们可能会忽略它们。由于篇幅原因,会在下一篇介绍 Material 组件的其他 Widget。

赞(0) 打赏
未经允许不得转载PHP开源Hub » Flutter 基础(五)Material 组件之 MaterialApp、Scaffold、AppBar

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

PHP开源Hub-致力于互联网开发者的成长

技术群聊软文发表

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏