百科知识

material什么意思,想知道这个词到底是什么意思吗

为了提升用户体验的便捷性,尽管Flutter鼓励开发者为每个widget构建专属设计,但在宏观架构层面,Flutter提供了Material和Cupertino两种主题风格的Widgets集合,允许开发者在这些风格的基础上进行个性化的定制与开发。

这两种风格在中文中分别翻译为“材料”和“库比蒂诺”,这样的命名确实有些难以理解……我们还是沿用其英文名称来称呼它们更为合适。

在本文中,我们将深入探讨Material主题的基础——MaterialApp。

如果你使用的是最新版本的Android Studio来创建一个Flutter项目,Android Studio会自动为你生成一个基于Flutter的应用框架。

让我们来查看一下自动生成的main.dart文件:

这个build方法所返回的widget构成了整个Flutter应用程序的根Widget。可以看到,默认情况下,它返回的是一个MaterialApp。

在上面的示例代码中,为MaterialApp设置了title、theme和home属性。

title代表了MaterialApp的标题,theme定义了整个MaterialApp的主题风格,而home则指定了应用程序启动时应该展示的主页面。

默认情况下,MyHomePage会返回一个类似于下面代码的Scaffold:

通过这样的结构,我们可以构建出常见的MaterialApp界面:

有了上述框架作为基础,我们就可以在home属性中构建自己的组件,从而开启Flutter的愉快app开发之旅。

那么,MaterialApp是否还有其他功能?它的底层原理是怎样的?接下来,让我们一起深入了解。

首先,我们来看一下MaterialApp的定义:

从定义可以看出,MaterialApp是一个StatefulWidget,这意味着它会根据用户的交互不同而重新构建子组件。由于MaterialApp通常代表整个应用程序,因此它需要处理许多复杂的交互情况,使用StatefulWidget是非常合理的。

接下来,我们来看看MaterialApp中可以配置的主题。

MaterialApp中包含以下几种theme:

ThemeData用于定义widget的主题样式,它包括colorScheme和textTheme两个部分。

为了简化操作,Flutter提供了两种简洁的主题创建方式:ThemeData.light和ThemeData.dark。当然,你也可以使用ThemeData.from来从ColorScheme中创建新的主题。

那么问题来了,一个应用程序为什么需要这么多ThemeData呢?

默认情况下,theme就是应用程序将使用的主要主题,但考虑到当前流行的主题切换功能,Flutter也提供了darkTheme这个选项。

如果同时设置了theme和darkTheme,那么将根据themeMode来决定具体使用哪个主题。

注意,默认的主题是ThemeData.light()

highContrastTheme和highContrastDarkTheme的存在也是因为某些系统需要高对比度和暗主题版本,这些ThemeData是可选的。

themeMode这个字段,如果取ThemeMode.system,那么默认会使用系统的主题配置,具体而言,是通过调用MediaQuery.platformBrightnessOf来查询系统到底是Brightness.light还是Brightness.dark.

虽然默认是ThemeMode.system,但你可以指定其为ThemeMode.light或者ThemeMode.dark.

与网页的首页类似,在MaterialApp中,我们也需要定义一些页面跳转的路由信息。

在讲解routes之前,我们需要明白Flutter中有两个与路由相关的定义,分别是routes和Navigator。

其中routes是路由的定义,它表示不同路径对应的widget地址,比如下面的routers的定义:

routers的类型是Map,对应的key就是路由地址,value就是路由地址对应的WidgetBuilder。

Navigator是一个Widget,用来对routes进行管理。

Navigator可以通过使用Navigator.pages、Navigator.push或者Navigator.pop来对routes进行管理。举个例子:

push:

pop:

对于MaterialApp来说,如果是/route,那么将会查找MaterialApp中的home属性对应的Widget,如果home对应的Widget不存在,那么会使用routers里面配置的。

如果上面的信息都没有,则说明需要创建router,则会调用onGenerateRoute方法来创建新的routers。

所以说onGenerateRoute是用来处理home和routers方法中没有定义的路由。你也可以将其看做是一种创建动态路由的方法。

最后,如果所有的route规则都不匹配的话,则会调用onUnknownRoute。

如果home、routes、onGenerateRoute、onUnknownRoute全都为空,并且builder不为空的话,那么将不会创建任何Navigator。

local是什么呢?local在国际化中表示一种语言,通过使用Local,你无需在程序中硬编码要展示的文本,从而实现APP的国际化支持。

在dart中,local可以这样使用:

在MaterialApp中,需要同时配置localizationsDelegates和supportedLocales:

supportedLocales中配置的是支持的locales,localizationsDelegates用来生成WidgetsLocalizations和MaterialLocalizations。

有关locale的具体使用,可以关注后续的文章。

MaterialApp是一个StatefulWidget,那么和它绑定的State叫做:_MaterialAppState,_MaterialAppState中有个build方法,返回的widget到底是什么呢?

可以看到,最终返回的是一个ScrollConfiguration,它的本质是返回一个包装在HeroControllerScope中的result。

什么是Hero呢?Hero在flutter中是一个组件,用来表示在路由切换的过程中,可以从老的路由fly到新的路由中。这样的一个飞行的动画,也叫做Hero动画。

而这个result其实是一个WidgetsApp。

WidgetsApp就是MaterialApp底层的Widget,它包装了应用程序通常需要的许多小部件。

WidgetsApp的一个主要功能就是将系统后退按钮绑定到弹出导航器或退出应用程序。

从实现上讲,MaterialApp和CupertinoApp都使用它来实现应用程序的基本功能。

MaterialApp作为Material风格的第一入口,希望大家能够熟练掌握它的用法。

本文的例子:https://github.com/ddean2009/learn-flutter.git

更多内容请参考 http://www.flydean.com/06-flutter-material-materialapp/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!