组件中设置body_Flutter必知必会的Material组件

本文介绍了Flutter中Material组件的基础知识,包括MaterialApp的路由管理、Scaffold的基本布局以及AppBar的使用。MaterialApp是实现Material Design应用的基础,Scaffold提供基本的屏幕结构,AppBar则用于展示顶部标题和操作。文章通过实例展示了如何创建和管理路由,以及使用Scaffold和AppBar构建用户界面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击上方“刘望舒”,马上关注,早上8:42推送

技术进阶关注“刘望舒”就对了

作者:刘望舒

http://liuwangshu.cn/flutter/primer/5-material-components.html

Flutter基础系列文章

移动开发的跨平台技术演进

是谁走漏了风声,我已经用flutter了

不会Dart,还搞什么Flutter?

开发Flutter应用前需要先掌握什么?

前言

在上一篇开发Flutter应用前需要先掌握什么?,我们学习了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。效果如下两个图所示。

4beaa12f0864cece04c4449ad504825c.png

c25eb7b42d7618efd51a92d3af0b025a.png

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:  {//1'/first': (BuildContext context) => FirstPage(),'/second': (BuildContext context) => SecondPage(),
      },
      initialRoute: '/first' ,
    );
  }
}class FirstPage extends StatelessWidget {@overrideWidget 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 {@overrideWidget 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:用于设置位于右下角的按钮。

效果如下所示:

66cf3cc620bd1f36afb0d49c8e226af7.png

可以看到在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: [
          IconButton(
            icon: Icon(Icons.share),
            onPressed: () {
              print('添加按钮');
            },
          ),
        ],
      ),
    );
  }
}

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

7536cdc3a269b059557febd1fd708bd8.png

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

4e570617c156ad9312a7742798bca2ad.png

总结

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

--------  END  ----------

推荐阅读

今天,我需要你的支持!

Android解析ActivityManagerService(二)ActivityTask和Activity栈管理

使用Flutter一年后,这是我得到的经验

你好,我是刘望舒,十年经验的资深架构师,著有两本业界知名的技术畅销书,多个知名技术大会的特邀演讲嘉宾。

如果你喜欢我的文章,就给公众号加个星标吧,方便阅读。

6e95b759cd62d1a24e2374663d0fece5.png

听说有人不敢点这里 ?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值