Flutter 入门指北之基础部件
作者: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,就是日常开发中,自定义部件通常继承的抽象类了。
StatelessWidget 是状态不可变部件,通过其构建的部件一般用来展示固定内容,例如需要展示固定的功能按钮列表,不需要根据不同界面状态进行修改其展示内容
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 入门指北之基础部件相关推荐
- Flutter 入门指北(Part 9)之弹窗和提示(SnackBar、BottomSheet、Dialog)
该文已授权公众号 「码个蛋」,转载请指明出处 前面的小节把常用的一些部件都介绍了,这节介绍下 Flutter 中的一些操作提示.Flutter 中的操作提示主要有这么几种 SnackBar.Botto ...
- Flutter 入门指北(Part 2)之基础部件
该文已授权公众号 「码个蛋」,转载请指明出处 上一节介绍了 Dart 的一些语法,以及配置环境的网址,这节我们就可以开始了解下 Flutter 了 主要包括 MaterialApp.Scaffold. ...
- Flutter 入门指北(Part 13)之网络
该文已授权公众号 「码个蛋」,转载请指明出处 前面讲完了常用的部件,BLoC 模式,数据持久化等常用的,今天再介绍个重头戏 -- 网络请求 HttpClient HttpClient 是 dart 自 ...
- Python 简单入门指北(二)
Python 简单入门指北(二) 2 函数 2.1 函数是一等公民 一等公民指的是 Python 的函数能够动态创建,能赋值给别的变量,能作为参传给函数,也能作为函数的返回值.总而言之,函数和普通变量 ...
- 计算机学习入门指北——计科软工网络信安侧重图析、解读专业术语、岗位分类、未来规划
申明:本博文偏技术向,主观性较强,其中部分理解必有偏差和误解,望指出改正! 计算机学习入门指北: 作为刚入学的计算机系学生,面对一片专业术语十分蒙.区块链?大数据?开源?数据库?嵌入式开发?前端后端? ...
- 【杭电数电实验】verilog入门指北
verilog入门指北 前言 指北内容 面向人群 基础实验 1-15 代码参考 正文 ISE 的安装 实验的基本操作流程 可能出现的问题 创建工程闪退 希望删除某一文件,实际上并没有删除 如何编写测试 ...
- 萌妹子Python入门指北(二)
原文来自 (ixindoo.com)[http://ixindoo.com/articles/662] 只写了第一篇就好久没更新了,为啥?因为妹子学编程的意愿不强了,我也不能逼迫她去学.不过后来收到部 ...
- 【Linux入门指北】第一篇 初识Linux
目录 前言 一.Linux操作系统的发展历史 1.Linux操作系统的诞生 2.Linux操作系统的发展 1.自由软件基金会(FSF) 2.GPL协议 3.GUN工程 二.Linux的不同发行版本 1 ...
- Python 简单入门指北(试读版)
本文是我小专栏中 Python 简单入门指北 一文的前半部分,如果你能坚持读完并且觉得有一定收获,建议阅读原文,只需一杯咖啡钱就可以阅读更精彩的部分,也可以订阅小专栏或者加入我的知识星球,价格都是 6 ...
最新文章
- LeetCode 7. 整数反转 Reverse Integer 官网答案的条件判定的一点思考
- 如何写windbg高级脚本---以访问文件的windbg脚本为例说明
- 海量存储系列下--转载,值得一读
- ajax滚动条动态加载,下拉滚动条,动态加载ajax加载数据
- eclipse进行远程调试教程,轻松搞定生产环境问题
- 工资的流水与真金、显性物价与隐性物价的名词说明
- 全网最全MATLAB学习归纳总结(建模学习必备)
- webstorm 破解方法(100%好使)
- 计算机网络自顶向下第六章,计算机网络 自顶向下方法 第六章(英文版).ppt
- 基于FileOpen的PDF文档加密
- 【数字设计】恒玄科技_笔试面试题目分享
- Python爬虫爬取豆瓣高分电影附源码(详细适合新手)
- 奥克兰大学计算机it专业介绍,新西兰奥克兰大学IT硕士专业解析
- Amazon ES现更名为Amazon OpenSearch Service并支持OpenSearch 1.0
- 解密阿里云效女程序员辰颜、异新代码诗!
- 如何从Google Play下载应用到电脑
- Executors.newFixedThreadPool(int threads)和Executors.newCachedThreadPool()
- CDN在前端开发中的作用
- cholesky 分解加速求解线性方程组
- 程式設計之道 冼鏡光
热门文章
- 传递矩阵的特征多项式
- 理由第三方搜索引擎查找真实ip
- 少女心多功能便签本,少女心便签软件办公版
- 在html中雪碧图的坐标怎么看,详解CSS Sprite雪碧图的应用
- 将算术表达式((a+b)+c*(d+e)+f)*(g+h) 转化为二叉树。并分别写出对该二叉树进行 先序、中序、后续和层次遍历得到的结果
- 使用特网云云主机的最显着原因之一
- HTML标签及效果大全
- DEJA_VU3D - Cesium功能集 之 076-缓冲区分析
- PPT在线预览 转换为图片实现方案 Apache POI 实现时踩坑:含嵌入文件ppt转换报错 ArrayStoreException
- 通信对抗干扰技术简单综述与MATLAB仿真