创建Flutter工程
flutter中工程名、文件夹和文件命名规则: 不要用驼峰、不要用大写、不要用中文。
类名可以用驼峰命名
创建工程方式
- 命令创建
// -i objc指定 OC语言,hello_flutter为工程名
flutter create -i objc hello_flutter
- 工具栏创建

- Android Studio启动页创建入口

配置Flutter SDK路径

Flutter工程配置
- 配置
android、ios语言类型,选择平台类型

- 选择工程
Project

- 选择模拟器,运行flutter工程


Flutter能运行在iOS与Android平台的原因是什么?
原因是在iOS与Android平台都安装了渲染引擎
Flutter与RN的本质区别?
-
RN:对原生UI即UIKit的包装,一旦原生UI产生更新,那么RN也需要进行更新,对原生的依赖性很强,RN有热更新 -
Flutter:把不同平台的渲染引擎安装在手机上,渲染引擎负责解析Dart代码进行页面展示,Flutter有热重载
优点:效率高,不依赖于UI,安卓iOS高度统一
缺点:引入渲染引擎会导致安装包体积增大
hello_flutter
更新Flutter版本
// 检查flutter环境配置
$ flutter doctor
// 更新flutter版本
$ flutter upgrade
解决Android Studio快捷键Cmd + Q的bug
Android Studio如果使用快捷键Cmd + Q强退,有可能会锁住当前的运行环境。一旦锁住运行环境,再次打开工程就有可能出现问题,原因是Android Studio中为了保护数据,里面有一个缓存机制。
解决方案
强退Android Studio导致flutter卡住了,就需要删除缓存文件,lockfile文件目录~/flutter/bin/cache/lockfile

开始Flutter编写
- 实现基层组件都需要导入头文件
material.dart,导入常用的素材类似于iOS中的UIKit
// 导入flutter的UI库,类似于iOS的UIKit
import 'package:flutter/material.dart';
- 在 iOS中运行APP 是在
window中,在Flutter中使用runApp,在这个里面添加组件,我们先来看看Text组件
// flutter入口函数
void main() {
runApp(const Center(
child: Text(
'helloFlutter',
textDirection: TextDirection.ltr,
),
));
}
- 当前运行页面里面有两个小部件
Center、Text,都是继承于Widget -
Center相当于OC中的view,child相当于subView的意思 -
Text相当于UILabel

flutter是增量渲染,不会改变组件内容,会直接用新的组件替换旧的组件,直接修改控件本身,以此改变值,所以效率很高;flutter没有页面层级,它只有一层页面
Dart中的var、final 和 const介绍
- var声明变量
void main() {
var a;//变量
print(a); // 打印结果为null
var b;//变量
b = "this is b !";
print(b); // 打印结果为 this is b !
}
-
var声明的变量,没有指定值,也没有指定类型,是一个动态类型,鼠标放上去会提示类型! -
dart中使用var声明变量,可以赋值不同类型的值,会自动推断变量的类型和Swift中是一样的效果。 -
var声明的变量如果没有初始化,那么它的值是null
- final声明变量
void main(){
final a = 10;
a = "hello"; // 运行报错
final b;
b = "hello";
print(b); // 打印结果为 hello
final c;
print(c); // 运行报错
}
-
final修饰的是一个最终的变量,不能再次赋值,否则会报错。也可以先声明再次赋值,但是只能赋值一次。 -
final适用声明以后不会改变的变量,也就类似一个常量的意思,它只能赋值一次。 -
final声明的变量,不赋值是不可以使用的。
- const声明常量
void main(){
const a;
a = 8; // 运行报错
const b = 8;
print(b); // 打印结果为 8
}
-
const修饰常量,声明的时候就得赋值,这也是和变量最大的区别! -
const常量也是不可以修改的,不可以再次赋值,这点和 final 一样。
自定义Widget
Widget分为两大类有状态stateful、无状态stateless,其实flutter小组件本质上都是无状态的,有状态只是定义了一些功能方便开发
-
无状态stateless表示不可变,如果要想改变,用新的组件替换当前组件 -
有状态stateful表示在当前树中,内部小组件可以更改状态。影响页面渲染的数据保存起来就是有状态的
自定义Widget
- 继承于
无状态小部件 - 要想让小部件显示在页面上,必须实现
build方法返回Widget
import 'package:flutter/material.dart';
void main() {
runApp(MyWidget());
}
// 如果main()里面只有一行代码,可以使用箭头函数进行缩写
//void main() => runApp(MyWidget());
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'helloFlutter',
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 14,color: Colors.orange,backgroundColor: Colors.white),
),
);
}
}

flutter热重载
如果iOS项目过大,编译时间会很长,虽然我们只改了一行代码,想要查看效果,也需要编译很长时间。而flutter开发中有一个好处,不需要重新启动flutter工程。比如我们改了Text文字大小,flutter会增量渲染我们修改的内容,不会重复渲染其他内容,即flutter热重载。增量渲染就是用新的小部件直接替换旧的小部件,将内容展示出来。
如果flutter项目是有状态的,那么数据发生了更改,就需要重新启动flutter项目。即渲染树发生了变化,需要重新启动flutter项目。
如果是有状态的小部件,而且状态发生了变化,热重载状态是不会清零的。如果要想把状态清零,需要重新启动项目
文字样式
flutter中创建模型对象是不会渲染的。这样的对象成员属性是可以更改的,一旦模型对象的属性发生变化,通过这个模型对象取到新的数据,用来创建新的小部件。
import 'package:flutter/material.dart';
void main() => runApp(MyWidget());
// 继承于无状态小部件
// 要想让小部件显示在页面上,必须实现build方法,返回Widget
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'helloFlutter123123',
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.orange,
)
),
);
}
}

Text组件
- 创建Text
Text()构造方法创建 - Text属性
textDirection 文本对齐 (必须要写的属性,否则内容不显示)
TextAlign.center 将文本对齐容器的中心。
TextAlign.end 对齐容器后缘上的文本。
TextAlign.justify 拉伸以结束的文本行以填充容器的宽度。即使用了decorationStyle才起效
TextAlign.left 对齐容器左边缘的文本。
TextAlign.right 对齐容器右边缘的文本。
TextAlign.start 对齐容器前缘上的文本。
maxLines 最大行数
overflow 处理字数溢出
TextOverflow.clip 剪切溢出的文本以修复其容器。
TextOverflow.ellipsis 使用省略号表示文本已溢出。
TextOverflow.fade 将溢出的文本淡化为透明。
textScaleFactor 字号系数
-
TextStyle style属性
color 文本颜色。
decoration 绘制文本装饰:
下划线(TextDecoration.underline)
上划线(TextDecoration.overline)
删除线(TextDecoration.lineThrough)
无(TextDecoration.none)
decorationStyle 绘制文本装饰的样式:
画一条虚线 TextDecorationStyle.dashed
画一条虚线 TextDecorationStyle.dotted
画两条线 TextDecorationStyle.double
画一条实线 TextDecorationStyle.solid
画一条正弦线(波浪线) TextDecorationStyle.wavy
fontWeight 绘制文本时使用的字体粗细:
FontWeight.bold 常用的字体重量比正常重。即w700
FontWeight.normal 默认字体粗细。即w400
FontWeight.w100 薄,最薄
FontWeight.w200 特轻
FontWeight.w300 轻
fontStyle 字体变体:
FontStyle.italic 使用斜体
FontStyle.normal 使用直立
textBaseline 对齐文本的水平线:
TextBaseline.alphabetic:文本基线是标准的字母基线
TextBaseline.ideographic:文字基线是表意字基线;
fontSize 字体大小
letterSpacing 水平字母之间的空间间隔(逻辑像素为单位)。可以使用负值来让字母更接近。
wordSpacing 单词之间添加的空间间隔(逻辑像素为单位)。可以使用负值来使单词更接近。
height 文本行与行的高度,作为字体大小的倍数
locale 用于选择区域特定字形的语言环境
background 文本背景色
foreground 文本的前景色
shadows 实现一些特殊效果
MaterialApp
- 素材App
- 有
home属性,主页面 - 有
debugShowCheckedModeBanner属性,便于我们在调试版本中做操作
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyWidget(),
);
}
}
// 继承于无状态小部件
// 要想让小部件显示在页面上,必须实现build方法,返回Widget
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'helloFlutter123123',
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.orange,
)
),
);
}
}

Scaffold小部件
-
Scaffold是Material Design布局结构的基本实现,此类提供了用于显示drawer、snackbar和底部sheet的API,是带有导航栏的小部件。 - 有
body属性,显示在导航栏下面的区域,需要传递一个Widget
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('FlutterDemo'),
),
),
);
}
}
// Scaffold主要属性
appBar:显示在界面顶部的一个 AppBar
body:当前界面所显示的主要内容
floatingActionButton: 在 Material 中定义的一个功能按钮。
persistentFooterButtons:固定在下方显示的按钮。
drawer:侧边栏控件
bottomNavigationBar:显示在底部的导航栏按钮栏。
backgroundColor:背景颜色
resizeToAvoidBottomPadding: 控制界面内容 body
是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被键盘盖住内容。默认值为 true。

自定义小部件MyWidget嵌入home页
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('FlutterDemo'),
),
body: MyWidget(),
),
);
}
}
// 继承于无状态小部件
// 要想让小部件显示在页面上,必须实现build方法,返回Widget
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const Center(
child: Text(
'helloFlutter123123',
textDirection: TextDirection.rtl,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
color: Colors.orange,
)
),
);
}
}

这个时候Center是相对于body居中的,Center小部件是相对于父视图居中的。
初探ListView
下面实现一个类似UITableView的页面
- 新建
model目录,里面创建Car.dart模型
// <!-- Car.dart文件 -->
class Car {
// {} 表示可选,可以给Car赋值,也可以不赋值
const Car({this.name, this.imageUrl});
final String? name;
final String? imageUrl;
}
-
main.dart文件中导入Car.dart
import 'model/Car.dart';
- ListView最终代码
import 'package:flutter/material.dart';
import 'model/car.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
// 去掉debug标识
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
class Home extends StatelessWidget {
//_是指文件内部!!!只在main.dart文件内部可以访问
Widget _itemForRow(BuildContext context, int index) {
return Container(
color: Colors.white,
margin: const EdgeInsets.all(10),
// 组件的排列有三种,横着 竖着 叠着
child: Column(
children: <Widget>[
// 命名构造函数,图片是异步加载
Image.network(datas[index].imageUrl!),
// SizedBox用于设置图片与文字的间隔,也可以用Container设置间隔
const SizedBox(
height: 10,
),
Text(
datas[index].name!,
style: const TextStyle(
fontWeight: FontWeight.w800,
fontSize: 18.0,
// italic表示斜体
fontStyle: FontStyle.italic,
),
),
],
));
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
backgroundColor: Colors.grey[100],
appBar: AppBar(
title: const Text('FlutterDemo'),
),
// listview构造函数
body: ListView.builder(
// 获取_itemForRow,上面定义的Widget
itemBuilder: _itemForRow,
itemCount: datas.length,
),
);
}
}
//引入`Car`模型数据
final List<Car> datas = [
const Car(
name: '保时捷918 Spyder',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-7d8be6ebc4c7c95b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '兰博基尼Aventador',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-e3bfd824f30afaac?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '法拉利Enzo',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-a1d64cf5da2d9d99?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: 'Zenvo ST1',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-bf883b46690f93ce?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '迈凯伦F1',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-5a7b5550a19b8342?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '萨林S7',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-2e128d18144ad5b8?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '科尼赛克CCR',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-01ced8f6f95219ec?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '布加迪Chiron',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-7fc8359eb61adac0?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '轩尼诗Venom GT',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-d332bf510d61bbc2.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
),
const Car(
name: '西贝尔Tuatara',
imageUrl:
'https://upload-images.jianshu.io/upload_images/2990730-3dd9a70b25ae6bc9?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240',
)
];

Container小部件
Container是一个容器类,一个拥有绘制、定位、调整大小的 widget,在Flutter中万物皆widget,widget是小部件的意思。类似于iOS中的UIView
-
Container组成
-
Container的最里层的是child元素,child元素首先会被padding包着,然后添加额外的constraints限制,最后添加margin -
Container自身尺寸的调节分两种情况:
Container在没有子节点(children)的时候,会试图去变得足够大。除非constraints是unbounded限制,在这种情况下,Container会试图去变得足够小。
带子节点的Container,会根据子节点尺寸调节自身尺寸,但是Container构造器中如果包含了width、height以及constraints,则会按照构造器中的参数来进行尺寸的调节。
- Container属性
-
key:Container唯一标识符,用于查找更新。 -
alignment:控制child的对齐方式,如果container或者container父节点尺寸大于child的尺寸,这个属性设置会起作用,有很多种对齐方式。 -
padding:decoration内部的空白区域,如果有child的话,child位于padding内部。padding与margin的不同之处在于,padding是包含在content内,而margin则是外部边界,设置点击事件的话,padding区域会响应,而margin区域不会响应。 -
color:用来设置container背景色,如果foregroundDecoration设置的话,可能会遮盖color效果。
import 'package:flutter/material.dart';
void main() => runApp(App());
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Container(
margin: EdgeInsets.all(10),
color: Colors.red,
alignment: Alignment(0,0),
child: Container(
margin: EdgeInsets.all(10),
color: Colors.brown,
width: 250,
height: 250,
child: Text(
'Hello World',
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 26,color: Colors.blue,backgroundColor: Colors.white),
),
),
);
}
}
