Flutter探索之路–Chapter 1
HelloWorld–国际惯例
国际惯例编写Hello World
import 'package:flutter/material.dart'; |
编译运行,如下:
引用库
flutter中,我们通过import语句进行引用
import 'dart:io'; |
当多个库中有冲突的名字的时候
Element element = new Element(); |
引用库的一部分
//导入foo |
开始学习–Flutter体系结构
框架层(Framework)
框架层是由Dart所编写的,里面包含:Material(Material Design风格的组件)、Cupertino(针对iOS风格的组件)、Widgets(组件)、Rendering(渲染)、Animation(动画)、Painting(绘制)、Gestures(手势)、Foundation(基础库)。通常开发者使用Framework层所提供的API去开发自己的项目。
引擎层(Engine)
引擎层(Engine)是由C++编写而成,里面包含Skia、Dart、Text三个部分。
- Skia:图形渲染库
- Dart:Dart VM虚拟机,用于编译和运行Dart代码
- Text:文本渲染(区分平台)
开始学习–Flutter程序结构
新建Flutter项目的结构和原生android的工程结构不一样,我们不能用android那种多module 多lib的结构去创建module和lib,因为我们的代码都是在
lib
目录里面完成的,除非要用到原生交互的代码,你可以在android
目录里面去写,然后在lib
目录里面去引用这些交互的代码。
- Android目录
- 存放的是Flutter与android原生交互的一些代码,这个路径的文件和创建单独的Android项目的基本一样的
- ios目录
- 存放的是Flutter与ios原生交互的一些代码。
- lib目录
- 存放的是Dart语言编写的代码,这里是
核心代码
。不管是Android平台,还是ios平台,安装配置好环境,可以把dart代码运行到对应的设备或模拟器上面
- 存放的是Dart语言编写的代码,这里是
- pubspec.yaml文件
- 配置依赖项的文件,比如配置远程pub仓库的依赖库,或者指定本地资源(图片、字体、音频、视频等)
开始学习–打包项目
创建keystore证书
创建命令:
keytool -genkey -alias flutterkey -keyalg RSA -keysize 1024 -keypass 123456 -validity 3650 -storepass 111111 -keystore D:\keytoolTest\flutterkeys.jks
命令解析:
- -genkey: 创建一个默认的.keystore文件
- -alias flutterkey: flutterkey就是keyAlias的值
- -keyalg: 指定密钥加密算法,命令中使用的是RSA算法
- -keysize: 密钥长度
- keyPassword: 密钥密码
- storePassword: 密钥库口令
- storeFile: 证书存放路径
代码中配置证书
进入android目录,新建一个key.properties文件,具体填写如下:
storePassword=111111 |
在Gradle中配置签名
build.gradle中修改如下:
def keystorePropertiesFile = rootProject.file("key.properties") |
signingConfigs中修改如下:
signingConfigs { |
buildTypes修改:
构建应用
- cd flutter项目根路径(例如:cd E:/flutter_demo )。
- 运行flutter build apk`(flutter build命令默认使用–release)。
- release版本的APK会生成在flutter项目根路径/build/app/outputs/apk/app-release.apk
Flutter的Theme
创建主题的方式是将ThemeData提供给MaterialApp构造函数,ThemeData的主要属性如下表
属性名 | 类型 | 说明 |
---|---|---|
accentColor | Color | 前景色(文本、按钮) |
accentColorBrightness | Brightness | accentColor的亮度 |
accentIconTheme | IconThemeData | 与突出颜色对照的图片主题 |
accentTextTheme | TextTheme | 与突出颜色对照的文本主题 |
backgroundColor | Color | 与primaryColor对比的颜色 |
bottomAppBarColor | Color | BottomAppBar的默认颜色 |
brightness | Brightness | 应用程序整体主题亮度 |
buttonColor | Color | RaisedButtons的默认填充色 |
buttonTheme | ButtonThemeData | 按钮等控件的默认配置主题 |
canvasColor | Color | MaterialType.canvas的默认颜色 |
cardColor | Color | Material用于Card的时候的颜色 |
chipTheme | ChipThemeData | Chip的样式 |
dialogBackgroundColor | Color | Dialog的背景色 |
disabledColor | Color | 不可用状态下的颜色 |
dividerColor | Color | 分割线颜色 |
errorColor | Color | 验证错误的颜色 |
hashColor | int | 对象hash值 |
highlightColor | Color | 高亮颜色 |
iconTheme | IconThemeData | 图标主题 |
indicatorColor | Color | TabBar选中时的颜色 |
inputDecorationTheme | InputDecorationTheme | InputDecoration主题 |
platform | TargetPlatform | Widget需要适配的目标类型 |
primaryColor | Color | App主要部分的背景色 |
primaryColorBrightness | Brightness | primaryColor的亮度 |
primaryColorDark | Color | primaryColor的暗色颜色 |
primaryColorLight | Color | primaryColor的亮色颜色 |
primaryIconTheme | IconThemeData | 一个与主色对比的图片主题 |
primaryTextTheme | TextThemeData | 一个与主色对比的文本主题 |
scaffoldBackgroundColor | Color | Scaffold的默认颜色 |
secondaryHeaderColor | Color | 有选定行时PaginatedDataTable标题的颜色 |
selectedRowColor | Color | 选中行时的高亮颜色 |
sliderTheme | SliderThemeData | slider的主题 |
splashColor | Color | 墨水喷溅的颜色 |
slpashFactory | InteractiveInkFeatureFactory | InkWall和InkResponse的墨水喷溅外观 |
textSelectionColor | Color | 选中文本的颜色 |
textSelectionHandleColor | Color | 当前文本的哪个部分的句柄颜色 |
textTheme | TextTheme | 与卡片和画布对比的文本颜色 |
toggleableActiveColor | Color | 切换widget的活动状态的颜色 |
unselectedWidgetColor | Color | widget处于非活动状态下的颜色 |
runtimeType | Type | 对象的运行时类型 |
如果没有提供主题,Flutter会创建一个默认主题
局部主题
关于主题,如果我们希望在应用程序的一部分使用其他的主题,我们可以有两种方式创建,创建特有的主题数据或者扩展父主题
创建特有的主题
实例化一个ThemeData对象,并传递给Theme,例如
Theme( |
扩展父主题
扩展父主题的时候,可以不需要覆盖所有的主题属性,我们可以通过copyWith方法来实现,例如
Theme( |
实战距离
我们设置应用的主题颜色为绿色,界面中间的文本背景为橙色、FloatingActionButton的背景颜色为橙色
import 'package:flutter/material.dart'; |
运行之后效果就是这样的
开始学习–Stateful和Stateless Widget
Stateless widgets 是不可变的, 这意味着它们的属性不能改变 - 所有的值都是最终的
Stateful widgets 持有的状态可能在widget生命周期中发生变化. 实现一个 stateful widget 至少需要两个类:
- 一个 StatefulWidget类
- 一个 State类。 StatefulWidget类本身是不变的,但是 State类在widget生命周期中始终存在
我们在通过VS Code的命令创建flutter project之后,默认生成的project就是一个有状态组件的示例,这个示例中,点击+号按钮,中间的数字就会+1。分析这个demo:
StatelessWidget
StatelessWidget从字面意思上来看是一个没有状态的widget,StatelessWidget没有要管理的内部状态,如果我们的页面不依赖于Widget对象本身的配置信息和BuldContext的时候就可以用无状态组件。
StatelessWidget的声明周期只有一个:build,它只会在三种情况下被调用:
- 将widget插入树中的时候,也就是第一次构建
- 当widget的父级更改了其配置时,例如,Less的父类改变了text的值
- 当它依赖的InheritedWidget发生变化时
StatefulWidget
官方Demo简单分析
代码中,MyHomePage继承自StatefulWidget类,并重写了createState方法:
class MyHomePage extends StatefulWidget { |
而状态类必须继承自State类,例如:
class _MyHomePageState extends State<MyHomePage> |
变量以下划线(_)开头,在Dart语言中使用下划线前缀标识符,会强制其变成私有的
之后定义一个变量_counter作为计数器,通过调用setState方法来控制这个变量
int _counter = 0; |
完整代码,可以创建工程之后阅读