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

本文首发于公众号「刘望舒」

关联系列
ReactNative入门系列
React Native组件
Flutter基础系列

前言

在上一篇文章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在此前的文章都用过,简单的使用这里就不介绍了,这里简单介绍下路由。
在Android开发中我们使用Intent来进行界面跳转,也称之为原生路由,后来出现了一些路由框架,比如ARouter。
在Flutter中进行界面跳转的就是路由,路由用Route类来进行表示,Navigator是对Route进行管理的Widget。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。效果如下两个图所示。

image
image

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:用于设置位于右下角的按钮。

效果如下所示:


image

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

3. AppBar

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

image
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类中。

image

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

image

总结

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

Flutter基础系列
Flutter基础(一)移动开发的跨平台技术演进
Flutter基础(二)Flutter开发环境搭建和Hello World
Flutter基础(三)Dart快速入门
Flutter基础(四)开发Flutter应用前需要掌握的Basic Widget
Flutter基础(五)Material组件之MaterialApp、Scaffold、AppBar
Flutter基础(六)Material组件之BottomNavigationBar、TabBar、Drawer
Flutter基础(七)Scrolling Widget之ListView、GridView、PageView
Flutter基础(八)手势相关Widget:GestureDetector和Dismissible
Flutter基础(九)资源和图片
Flutter基础(十)布局Widget快速入门
Flutter基础(十一)网络请求(Dio)与JSON数据解析
Flutter基础(十二)路由(页面跳转)与数据传递
Flutter基础(十三)Flutter与Android的相互通信


<div align=center>这里不仅分享大前端、Android、Java等技术,还有程序员成长类文章。</div>
<div align=center><img src="https://user-gold-cdn.xitu.io/2019/7/10/16bd7d4e754df569?w=234&h=231&f=jpeg&s=34771" width="260"/></div>

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容