简介

为了简化大家的应用,尽管flutter举荐所有的widget都有本人来进行搭建,然而在大框架下面,flutter提供了Material和Cupertino两种主题格调的Widgets汇合,大家能够在这两种格调的继承上进行个性化定制和开发。

这两种格调翻译成中文就是:资料和库比蒂诺?什么鬼....咱们还是应用默认的英文名来称说它们吧。

本文咱们将会深刻解说Material主题的根底-MaterialApp。

MaterialApp初探

如果你应用最新的android Studio创立一个flutter我的项目的话,android Studio会主动为你创立一个基于flutter的应用程序。

咱们来看下主动创立的main.dart文件:

  Widget build(BuildContext context) {    return MaterialApp(      title: 'Flutter Demo',      theme: ThemeData(        primarySwatch: Colors.blue,      ),      home: const MyHomePage(title: 'Flutter Demo Home Page'),    )  }

这个build办法返回的widget就是这个flutter应用程序的根Widget。能够看到,默认状况下是返回一个MaterialApp。

在下面的样例代码中,为MaterialApp设置了tile,theme和home属性。

title是MaterialApp的题目,theme是整个MaterialApp的主题,home示意的是app进入时候应该展现的主页面。

默认状况下MyHomePage会返回一个相似上面代码的Scaffold:

    return Scaffold(      appBar: AppBar(        title: Text(widget.title),      ),      body: Center(        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: const <Widget>[            Text(              'home page',            ),          ],        ),      ),    );

这样咱们能够失去常见的MaterialApp界面:

MaterialApp详解

有了下面的框架,咱们就能够在home中构建本人的组件,从而开始flutter的欢快app之旅。

那么MaterialApp还有其余的什么性能吗?它的底层原理是怎么样的呢?一起来看看吧。

首先是MaterialApp的定义:

class MaterialApp extends StatefulWidget

能够看到MaterialApp是一个StatefulWidget,示意MaterialApp可能会依据用户的输出不同,从新build子组件,因为通常来说MaterialApp示意一个应用程序总体,所以它须要思考很多简单的交互状况,应用StatefulWidget是很正当的。

MaterialApp中的theme

接下来咱们看下MaterialApp能够配置的主题。

MaterialApp中有上面几种theme:

  final ThemeData? theme;  final ThemeData? darkTheme;  final ThemeData? highContrastTheme;  final ThemeData? highContrastDarkTheme;  final ThemeMode? themeMode;

ThemeData用来定义widget的主题款式,ThemeData包含colorScheme和textTheme两局部。

为了简略起见,flutter提供了两个简洁的Theme创立形式,别离是ThemeData.light和ThemeData.dark。 当然你也能够应用ThemeData.from从ColorScheme中创立新的主题。

那么问题来了,一个app为什么有这么多ThemeData呢?

默认状况下theme就是app将会应用的theme,然而思考到当初风行的theme切换的状况,所以也提供了darkTheme这个选项。

如果theme和darkTheme都设置的话,那么将会依据themeMode来决定具体到底应用哪个主题。

留神,默认的主题是ThemeData.light()

highContrastTheme和highContrastDarkTheme的存在也是因为在某些零碎中须要high contrast和dark的主题版本,这些ThemeData是可选的。

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

尽管默认是ThemeMode.system,然而你也能够指定其为ThemeMode.light或者ThemeMode.dark.

MaterialApp中的routes

和web页面的首页一样,在MaterialApp中,咱们也须要定义一些页面跳转的路由信息。

在解说routes之前,咱们须要明确flutter中有两个和路由相干的定义,别离是routes和Navigator。

其中routes是路由的定义,它示意的是不同门路对应的widget地址,比方上面的routers的定义:

routes: <String, WidgetBuilder> {       '/a': (BuildContext context) => MyPage(title: 'page A'),       '/b': (BuildContext context) => MyPage(title: 'page B'),       '/c': (BuildContext context) => MyPage(title: 'page C'),     },

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

Navigator是一个Widget,用来对routers进行治理。

Navigator能够通过是用Navigator.pages、Navigator.push或者Navigator.pop来对routers进行治理。举个例子:

push:

 Navigator.push(context, MaterialPageRoute<void>(   builder: (BuildContext context) {     return Scaffold(       appBar: AppBar(title: Text('My Page')),       body: Center(         child: TextButton(           child: Text('POP'),           onPressed: () {             Navigator.pop(context);           },         ),       ),     );   }, ));

pop:

Navigator.pop(context);

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

如果下面的信息都没有,则阐明须要创立router,则会调用onGenerateRoute办法来创立新的routers。

所以说onGenerateRoute是用来解决home和routers办法中没有定义的路由。你也能够将其看做是一种创立动静路由的办法。

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

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

MaterialApp中的locale

local是什么呢?local在国际化中示意的是一种语言,通过应用Local,你不必再程序中硬编码要展现的文本,从而做到APP的国际化反对。

dart中的local能够这样应用:

const Locale swissFrench = Locale('fr', 'CH');const Locale canadianFrench = Locale('fr', 'CA');

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

MaterialApp(  localizationsDelegates: [    // ... app-specific localization delegate[s] here    GlobalMaterialLocalizations.delegate,    GlobalWidgetsLocalizations.delegate,  ],  supportedLocales: [    const Locale('en', 'US'), // English    const Locale('he', 'IL'), // Hebrew    // ... other locales the app supports  ],  // ...)

supportedLocales中配置的是反对的locales,localizationsDelegates用来生成WidgetsLocalizations和MaterialLocalizations.

无关locale的具体应用,能够关注后续的文章。

MaterialApp和WidgetsApp

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

    return ScrollConfiguration(      behavior: widget.scrollBehavior ?? const MaterialScrollBehavior(),      child: HeroControllerScope(        controller: _heroController,        child: result,      ),    );

能够看到,最终返回的是一个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/

最艰深的解读,最粗浅的干货,最简洁的教程,泛滥你不晓得的小技巧等你来发现!

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