作者:Kuky_xs

原文:https://www.jianshu.com/p/8ddb16902ce6

前言

主要包括 MaterialApp、Scaffold、Text、Image、Icon、Button 以及 AppBar 部分内容,准备出发~

看完这篇文章你就在知道怎么写以上效果了

Flutter runApp

新建 flutter 项目后,可以看到 lib 下的 main.dart 中 void main() => runApp(MyApp());这句就是程序的入口了。这里可以简单看下源码

void runApp(Widget app) {WidgetsFlutterBinding.ensureInitialized()..attachRootWidget(app)..scheduleWarmUpFrame();
}///....
static WidgetsBinding ensureInitialized() {if (WidgetsBinding.instance == null)WidgetsFlutterBinding();return WidgetsBinding.instance;
}///....
void attachRootWidget(Widget rootWidget) {_renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(container: renderView,debugShortDescription: '[root]',child: rootWidget).attachToRenderTree(buildOwner, renderViewElement);
}

首先会创建一个 WidgetsBinding 单例对象,然后把传入的 App 添加到 rootWidget中,scheduleWarmUpFrame 方法比较长,这边看下对该方法的注释第一句就能了解方法的主要功能了

Schedule a frame to run as soon as possible

「安排框架尽快运行起来」(原谅我这渣英语,只能看懂不会翻译..大概就是「快速启动框架」的意思吧)

Flutter App

接着看下 MyApp 这个类,继承自 StatelessWidget 并在 build 方法返回一个 MaterialApp 实例,(偷偷讲下,其实这边还可以返回 CupertinoApp,这是一个 iOS 风格的 widget,基本上你看到部件带 「Cupertino」的都是 iOS 风格的 widget,这里先不讲 iOS 风格的部件,目前 flutter 对 Cupertino 系列的 widget 支持不是很好,包括部件的广度,多语言的支持等等方面都不是很友好,所以我们还是继续看 MD 风格的 Android 部件吧~),这里先看下 MaterialApp 的构造函数,介绍一些常用的参数

const MaterialApp({Key key,this.navigatorKey,this.home, // 主界面的内容 widgetthis.routes = const <String, WidgetBuilder>{}, // 带 router 和路由跳转有关this.initialRoute,this.onGenerateRoute,this.onUnknownRoute,this.navigatorObservers = const <NavigatorObserver>[], this.builder,this.title = '', // *类似标题this.onGenerateTitle, // 主要用于多语言情况下,需要根据当前语言替换 title,需要使用该值this.color, // 主题色,如果该值未设置,取 theme.primaryColor,未设置 theme 则取蓝色this.theme, // App 的主题风格,包括主题色,按钮默认颜色等等this.locale, // 带 locale 的和多语言适配相关this.localizationsDelegates,this.localeListResolutionCallback,this.localeResolutionCallback,this.supportedLocales = const <Locale>[Locale('en', 'US')],this.debugShowMaterialGrid = false, this.showPerformanceOverlay = false,this.checkerboardRasterCacheImages = false,this.checkerboardOffscreenLayers = false,this.showSemanticsDebugger = false,this.debugShowCheckedModeBanner = true, // debug 模式下,是否显示 DEBUG 标示横幅})

MaterialApp 继承自 StatefulWidget,它和 MyApp 所继承的类 StatelessWidget,就是日常开发中,自定义部件通常继承的抽象类了。

  1. StatelessWidget 是状态不可变部件,通过其构建的部件一般用来展示固定内容,例如需要展示固定的功能按钮列表,不需要根据不同界面状态进行修改其展示内容

  2. StatefulWidget 是可改变状态的部件,比如我们需要通过网络或者数据库获取数据,然后修改部件锁展示的数据内容,则需要通过 StatefulWidget 来构建。当然,不是说 StatelessWidget 不能实现修改界面数据的功能,这就需要涉及到 状态管理 的概念了,后面有机会再讲,这边先埋坑【坑1】

Flutter Scaffold

进入 App 后就需要构建界面了,Flutter 提供了 Scaffold 来快速构建一个 MaterialDesign 风格的界面,还是先看下 Scaffold 的构造函数吧,了解几个比较常用的部分。

const Scaffold({Key key,this.appBar, // 界面顶部的那条栏,这边需要返回一个 AppBar 实例this.body, // 界面的内容部分this.floatingActionButton, // 悬浮部分,可以通过 floatingActionButtonLocation 设置位置this.floatingActionButtonLocation,this.floatingActionButtonAnimator,this.persistentFooterButtons,this.drawer, // 侧滑抽屉部分,从左侧滑出(应该和语言有关,和文字方向同向)this.endDrawer, // 侧滑抽屉部分,从右侧滑出this.bottomNavigationBar, // 底部导航栏,就是通常看到的底部 TAB 切换部件this.bottomSheet, // 展示从底部弹出的,起到提示作用的,通过 showModalBottomSheet 展示this.backgroundColor, // 界面的背景色this.resizeToAvoidBottomPadding = true, // 避免 body 被底部弹出部件填充,例如输入法键盘this.primary = true, // 当前的 Scaffold 是否需要被展示在屏幕最上层})

来张图吧,简洁明了

了解完 Scaffold 的整体构造后,我们从上到下,通过构造函数来了解下各个 Widget的使用方法

AppBar

AppBar({Key key,this.leading, // 用于设置 AppBar 前置的按钮,例如设置返回我们需要的返回按钮等this.automaticallyImplyLeading = true, // 是否使用系统默认生成的按钮,如果替换 leading 的默认按钮,最好将该属性设置成 falsethis.title, // AppBar 所需要展示的组件,传入一个 Widget 实例,通常使用 Text 展示一个标题this.actions, // AppBar 末尾悬浮的一些操作组件,例如常见的会在末尾设置一个「...」按钮,点击弹出一个 menue 提供给用户操作选择this.flexibleSpace, // AppBar 的背景,可以设置颜色,背景图等等 this.bottom, // bottom 用于展示顶部导航 TABthis.elevation = 4.0,this.backgroundColor, // AppBar 的背景色,如果只需要修改颜色,可以不通过 flexibleSpace 修改this.brightness,this.iconTheme, // 按钮的默认样式this.textTheme, // 文字的默认样式this.primary = true,this.centerTitle, // 是否将展示的 title 居中this.titleSpacing = NavigationToolbar.kMiddleSpacing, // AppBar title 两侧的空白间隔this.toolbarOpacity = 1.0,this.bottomOpacity = 1.0,})

在展示 AppBar 的 demo 之前,我们先学习几个基本的组件 Text、Image、Icon、Button 分布用于展示文字,图片,图标,按钮

Text

const Text(this.data, { // Text 需要展示的文字Key key,this.style, // 文字的样式,包括颜色,大小,间距等等属性,这边就不继续展示 TextStyle 构造函数了,不然我怕大家都不想继续看了,稍后通过例子来说明this.textAlign, // 文字的对齐方式,包括左对齐,右对齐,居中等,详见 TextAlign 类this.textDirection, // 文字方向,ltr(left to right) 或者 rtl(right to left)this.locale, this.softWrap, // 当文字一行显示不完是否换行this.overflow, // 如果超出限制的行数,以哪种方式省略未展示的内容this.textScaleFactor, // 文字缩放比例this.maxLines, // 最多展示的行数this.semanticsLabel,})

说了那么多,相信很多小伙伴都要急着撸代码了吧,接着来展示一些 Text 的示例,接下来的例子都会直接替换 HomePage 内的展示内容,其余都是相同的,接下来请关注 Text 别的部件先忽略,后面会介绍,这边先埋坑【坑2】

import 'package:flutter/material.dart';void main() => runApp(DemoApp());class DemoApp extends StatelessWidget {@overrideWidget build(BuildContext context) {return MaterialApp(title: 'Flutter Demo',debugShowCheckedModeBanner: false,theme: ThemeData(primarySwatch: Colors.lightBlue),home: HomePage(),);}
}class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(),body: Container(padding: const EdgeInsets.only(top: 10.0),child: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[Text('绿色背景黑色文字展示',style: TextStyle(color: Colors.black, // 设置文字颜色,不可和 foreground 同时设置fontSize: 24.0, // 字体大小letterSpacing: 2.0, // 每个字符之间的间隔background: Paint()..color = Colors.green)), // 背景色Text('这是一个带红色下划线的文字展示',style: TextStyle(color: Colors.black,fontSize: 24.0,// 文字装饰线,除了 underline 还有 overline, lineThrough,// 不同的样式小伙伴可以通过自己修改代码来查看decoration: TextDecoration.underline,// 文字装饰线的类型,除了 solid 还有 double,dotted,dashed,wavy 可选decorationStyle: TextDecorationStyle.solid,// 装饰线的颜色decorationColor: Colors.red))],)),));}
}

该部分代码查看源码 text_main.dart 文件

最后的展示效果如下图:

Image

按照惯例,我们还是先看下 Image 的构造函数吧

const Image({Key key,// 一个 ImageProvider 实例,但是 ImageProvider 是一个抽象类,Flutter 已经给我们提供如下// AssetImage,NetworkImage,FileImage,MemoryImage 这四种图片加载器,为了方便调用// 我们可以直接通过 Image.asset, Image.network, Image.file, Image.memory 简化,// 通过方法名,可以看出分别从 asset 文件,网络,文件,内存中加载图片@required this.image, this.semanticLabel,this.excludeFromSemantics = false,this.width, // 图片宽度this.height, // 图片高度this.color, // 图片背景色this.colorBlendMode, // color 和图片的混合模式(这个值比较多,可以一个个尝试)this.fit, // 图片填充方式 fill, cover, contain, fillWidth, fillHeight, scaleDown, nonethis.alignment = Alignment.center, // 对齐方式this.repeat = ImageRepeat.noRepeat, // 若未填充满空间,重复展示的方式this.centerSlice,this.matchTextDirection = false,this.gaplessPlayback = false,this.filterQuality = FilterQuality.low,})

好了好了,我知道你们又想自己写代码尝试下了,在这之前,需要你先准备一张本地图片,然后在项目的根目录,也就是 lib 文件夹同层,创建一个新的文件夹,命名为 images,把你准备好的图片放到这个目录下。放好之后打开 pubspec.yaml 把图片资源文件注册下

# The following p is specific to Flutter.
flutter:# The following line ensures that the Material Icons font is# included with your application, so that you can use the icons in# the material Icons class.uses-material-design: true# 这边注册资源文件,以后有图片文件也可以只注册 images 文件夹,会自动读取内部的文件assets:- images/ali.jpg

注册完成后,就可以继续愉快的撸代码了~

class HomePage extends StatelessWidget {final String _assetAli = 'images/ali.jpg';final String _picUrl ='https://timg05.bdimg.com/timg?wapbaike&quality=60&size=b1440_952&cut_x=143&cut_y=0&cut_w=1633&''cut_h=1080&sec=1349839550&di=cbbc175a45ccec5482ce2cff09a3ae34&''src=http://imgsrc.baidu.com/baike/pic/item/4afbfbedab64034f104872baa7c379310b551d80.jpg';@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(),body: Container(padding: const EdgeInsets.only(top: 10.0),child: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[// 这种展示图片方式和下一种会有相同的效果Image(image: AssetImage(_assetAli), width: 80.0, height: 80.0),// 接下来加载图片都会使用这些比较方便的方法Image.asset(_assetAli, width: 80.0, height: 80.0),// 加载一张网络图片Image.network(_picUrl,height: 80.0,// 横向重复repeat: ImageRepeat.repeatX,// MediaQuery.of(context).size 获取到的为上层容器的宽高width: MediaQuery.of(context).size.width),// 通过设置混合模式,可以看到图片展示的样式已经修改Image.asset(_assetAli,width: 80.0, height: 80.0, color: Colors.green, colorBlendMode: BlendMode.colorDodge),// 会优先加载指定的 asset 图片,然后等网络图片读取成功后加载网络图片,会通过渐隐渐现方式展现// cover 方式按照较小的边布满,较大的给切割// contain 会按照最大的边布满,较小的会被留白// fill 会把较大的一边压缩// fitHeight, fitWidth 分别按照长宽来布满FadeInImage.assetNetwork(placeholder: _assetAli, image: _picUrl, width: 120.0, height: 120.0, fit: BoxFit.cover),// Icon 相对属性少了很多,需要传入一个 IconData 实例,flutter 提供了很多图标,// 但是实际情况我们需要加入我们自己的图标,这边再埋坑【坑3】// size 为图标显示的大小,color 为图标的颜色,这边通过 Theme 获取主题色调Icon(Icons.android, size: 40.0, color: Theme.of(context).primaryColorDark)],)),));}
}

该部分代码查看源码 image_main.dart 文件

最后的效果如下:

Button

Flutter 提供了各种类型的 Button 几乎是大同小异的,这边就抽取一些比较常用的展示下效果,常用的主要有 RaisedButton 、FlatButton、IconButton、OutlineButton、MaterialButton、FloatActionButton、FloatingActionButton.extended

Button 都有一个 onPress 参数,是 VoidCallback 类型的参数,通过查看源码可以知道 VoidCallback 是无参无返回值的一种类型参数。如果该参数传入的值为 null 那么这个按钮的就不可点击状态,无点击效果,等会可以在例子中查看。还有就是 child 参数,这里就是传入你需要展示的内容,比如 Text、Icon 等等。别的参数基本可以通过参数名了解,这边不扩展了(再看源码我怕你们都不想继续看下去了...)

Talk is cheap, show me the code

class HomePage extends StatelessWidget {@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(),body: Container(padding: const EdgeInsets.only(top: 10.0),child: Center(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[RaisedButton(onPressed: () {print('This is a Rased Button can be clicked');},child: Text('Raised Enable'),),RaisedButton(onPressed: null, child: Text('Raised Disable')),FlatButton(onPressed: () => print('This is a Flat Button can be clicker'),child: Text('Flat Enable'),),FlatButton(onPressed: null, child: Text('Flat Disable')),IconButton(icon: Icon(Icons.android), onPressed: () {}),IconButton(icon: Icon(Icons.android), onPressed: null),MaterialButton(onPressed: () {}, child: Text('Material Enable')),MaterialButton(onPressed: null, child: Text('Material Disable')),OutlineButton(onPressed: () {}, child: Text('Outline Enable')),OutlineButton(onPressed: null, child: Text('Outline Enable')),],)),),floatingActionButton:FloatingActionButton.extended(onPressed: () {}, icon: Icon(Icons.android), label: Text('Android')),floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,);}
}

该部分代码查看源码 button_main.dart 部分

最终的效果图:

这篇终于到末尾了,最后留了 3 个坑等以后解决

最后代码的地址还是要的:

文章 demo 的地址:https://github.com/kukyxs/flutter_arts_demos_app

一个写着玩的电影 App 地址,含括日常开发的常用功能:https://github.com/kukyxs/flutter_timer_movie

一个课程(当时买了想看下代码规范的,代码更新会比较慢,虽然是跟着课上的一些写代码,但是还是做了自己的修改,很多地方看着不舒服,然后就改成自己的实现方式了):https://github.com/kukyxs/flutter_shop

如果对你有帮助的话,记得给个 Star,先谢过,你的认可就是支持我继续写下去的动力~

作者其他文章:

  • 《django入门:环境及项目搭建》

  • 《django入门:数据模型》

  • 《django入门:视图及模版》

  • 《django入门:Admin管理系统及表单》

  • 《django入门:通用视图类重构视图》

  • 《用django写接口(入门篇)》

  • 《用django写接口(优化篇)》

  • 《用django写接口(实战篇)》

今日问题:

Flutter你怎么看?

你在看吗?

Flutter 入门指北之基础部件相关推荐

  1. Flutter 入门指北(Part 9)之弹窗和提示(SnackBar、BottomSheet、Dialog)

    该文已授权公众号 「码个蛋」,转载请指明出处 前面的小节把常用的一些部件都介绍了,这节介绍下 Flutter 中的一些操作提示.Flutter 中的操作提示主要有这么几种 SnackBar.Botto ...

  2. Flutter 入门指北(Part 2)之基础部件

    该文已授权公众号 「码个蛋」,转载请指明出处 上一节介绍了 Dart 的一些语法,以及配置环境的网址,这节我们就可以开始了解下 Flutter 了 主要包括 MaterialApp.Scaffold. ...

  3. Flutter 入门指北(Part 13)之网络

    该文已授权公众号 「码个蛋」,转载请指明出处 前面讲完了常用的部件,BLoC 模式,数据持久化等常用的,今天再介绍个重头戏 -- 网络请求 HttpClient HttpClient 是 dart 自 ...

  4. Python 简单入门指北(二)

    Python 简单入门指北(二) 2 函数 2.1 函数是一等公民 一等公民指的是 Python 的函数能够动态创建,能赋值给别的变量,能作为参传给函数,也能作为函数的返回值.总而言之,函数和普通变量 ...

  5. 计算机学习入门指北——计科软工网络信安侧重图析、解读专业术语、岗位分类、未来规划

    申明:本博文偏技术向,主观性较强,其中部分理解必有偏差和误解,望指出改正! 计算机学习入门指北: 作为刚入学的计算机系学生,面对一片专业术语十分蒙.区块链?大数据?开源?数据库?嵌入式开发?前端后端? ...

  6. 【杭电数电实验】verilog入门指北

    verilog入门指北 前言 指北内容 面向人群 基础实验 1-15 代码参考 正文 ISE 的安装 实验的基本操作流程 可能出现的问题 创建工程闪退 希望删除某一文件,实际上并没有删除 如何编写测试 ...

  7. 萌妹子Python入门指北(二)

    原文来自 (ixindoo.com)[http://ixindoo.com/articles/662] 只写了第一篇就好久没更新了,为啥?因为妹子学编程的意愿不强了,我也不能逼迫她去学.不过后来收到部 ...

  8. 【Linux入门指北】第一篇 初识Linux

    目录 前言 一.Linux操作系统的发展历史 1.Linux操作系统的诞生 2.Linux操作系统的发展 1.自由软件基金会(FSF) 2.GPL协议 3.GUN工程 二.Linux的不同发行版本 1 ...

  9. Python 简单入门指北(试读版)

    本文是我小专栏中 Python 简单入门指北 一文的前半部分,如果你能坚持读完并且觉得有一定收获,建议阅读原文,只需一杯咖啡钱就可以阅读更精彩的部分,也可以订阅小专栏或者加入我的知识星球,价格都是 6 ...

最新文章

  1. LeetCode 7. 整数反转 Reverse Integer 官网答案的条件判定的一点思考
  2. 如何写windbg高级脚本---以访问文件的windbg脚本为例说明
  3. 海量存储系列下--转载,值得一读
  4. ajax滚动条动态加载,下拉滚动条,动态加载ajax加载数据
  5. eclipse进行远程调试教程,轻松搞定生产环境问题
  6. 工资的流水与真金、显性物价与隐性物价的名词说明
  7. 全网最全MATLAB学习归纳总结(建模学习必备)
  8. webstorm 破解方法(100%好使)
  9. 计算机网络自顶向下第六章,计算机网络 自顶向下方法 第六章(英文版).ppt
  10. 基于FileOpen的PDF文档加密
  11. 【数字设计】恒玄科技_笔试面试题目分享
  12. Python爬虫爬取豆瓣高分电影附源码(详细适合新手)
  13. 奥克兰大学计算机it专业介绍,新西兰奥克兰大学IT硕士专业解析
  14. Amazon ES现更名为Amazon OpenSearch Service并支持OpenSearch 1.0
  15. 解密阿里云效女程序员辰颜、异新代码诗!
  16. 如何从Google Play下载应用到电脑
  17. Executors.newFixedThreadPool(int threads)和Executors.newCachedThreadPool()
  18. CDN在前端开发中的作用
  19. cholesky 分解加速求解线性方程组
  20. 程式設計之道 冼鏡光

热门文章

  1. 传递矩阵的特征多项式
  2. 理由第三方搜索引擎查找真实ip
  3. 少女心多功能便签本,少女心便签软件办公版
  4. 在html中雪碧图的坐标怎么看,详解CSS Sprite雪碧图的应用
  5. 将算术表达式((a+b)+c*(d+e)+f)*(g+h) 转化为二叉树。并分别写出对该二叉树进行 先序、中序、后续和层次遍历得到的结果
  6. 使用特网云云主机的最显着原因之一
  7. HTML标签及效果大全
  8. DEJA_VU3D - Cesium功能集 之 076-缓冲区分析
  9. PPT在线预览 转换为图片实现方案 Apache POI 实现时踩坑:含嵌入文件ppt转换报错 ArrayStoreException
  10. 通信对抗干扰技术简单综述与MATLAB仿真