// m[“name”]=“李四”;
// print(person);
// print(m);
//常用属性:
// Map person={
// “name”:“张三”,
// “age”:20,
// “sex”:“男”
// };
// print(person.keys.toList());
// print(person.values.toList());
// print(person.isEmpty);
// print(person.isNotEmpty);
//常用方法:
Map person={
“name”:“张三”,
“age”:20,
“sex”:“男”
};
// person.addAll({
// “work”:[‘敲代码’,‘送外卖’],
// “height”:160
// });
// print(person);
// person.remove(“sex”);
// print(person);
print(person.containsValue(‘张三’));
}
=======================================================================================
/*
forEach
map
where
any
every
*/
void main(){
// List myList=[‘香蕉’,‘苹果’,‘西瓜’];
// for(var i=0;i<myList.length;i++){
// print(myList[i]);
// }
// for(var item in myList){
// print(item);
// }
// myList.forEach((value){
// print(“$value”);
// });
// List myList=[1,3,4];
// List newList=new List();
// for(var i=0;i<myList.length;i++){
// newList.add(myList[i]*2);
// }
// print(newList);
// List myList=[1,3,4];
// var newList=myList.map((value){
// return value*2;
// });
// print(newList.toList());
// List myList=[1,3,4,5,7,8,9];
// var newList=myList.where((value){
// return value>5;
// });
// print(newList.toList());
// List myList=[1,3,4,5,7,8,9];
// var f=myList.any((value){ //只要集合里面有满足条件的就返回true
// return value>5;
// });
// print(f);
// List myList=[1,3,4,5,7,8,9];
// var f=myList.every((value){ //每一个都满足条件返回true 否则返回false
// return value>5;
// });
// print(f);
// set
// var s=new Set();
// s.addAll([1,222,333]);
// s.forEach((value)=>print(value));
//map
Map person={
“name”:“张三”,
“age”:20
};
person.forEach((key,value){
print(“ k e y − − − key--- key−−−value”);
});
}
==================================================================================
/*
Dart中抽象类: Dart抽象类主要用于定义标准,子类可以继承抽象类,也可以实现抽象类接口。
1、抽象类通过abstract 关键字来定义
2、Dart中的抽象方法不能用abstract声明,Dart中没有方法体的方法我们称为抽象方法。
3、如果子类继承抽象类必须得实现里面的抽象方法
4、如果把抽象类当做接口实现的话必须得实现抽象类里面定义的所有属性和方法。
5、抽象类不能被实例化,只有继承它的子类可以
extends抽象类 和 implements的区别:
1、如果要复用抽象类里面的方法,并且要用抽象方法约束自类的话我们就用extends继承抽象类
2、如果只是把抽象类当做标准的话我们就用implements实现抽象类
*/
======================================================================
安装最新的 Xcode
下载androidstudio
https://developer.android.google.cn/studio
下载 Flutter SDK
https://flutter.dev/docs/development/tools/sdk/releases?tab=macos
把下载好的 Flutter SDK 随便减压到你想安装 Sdk 的目录如
/Users/cc/flutter
把 Flutter 安装目录的 bin 目录配置到环境变量,然后把 Flutter 国内镜像也配置到环境 变量里面
vim ~/.zshrc
export PATH=/Users/cc/flutter/bin:$PATH
export ANDROID_HOME=“/Users/cc/Library/Android/sdk”
export PATH= P A T H : {PATH}: PATH:{ANDROID_HOME}/tools
export PATH= P A T H : {PATH}: PATH:{ANDROID_HOME}/platform-tools
export PUB_HOSTED_URL=https://pub.flutter-io.cn
export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
source ~/.zshrc
flutter -h 如果能出来一些命令说明 flutter sdk 配置成功。
注意如果配置完成后输入 flutter -h 告诉你 flutter 不是内置命令之类的错误的话,可能 sdk 没有配置成功,也可能 sdk 下载的时候没有下载全
运行 flutter doctor 命令检测环境
====================================================================
每一个 flutter 项目的 lib 目录里面都有一个 main.dart 这个文件就是 flutter 的入口文件
main.dart 里面的
void main() {
runApp(MyApp());
}
//也可以简写
void main() => runApp(MyApp());
其中的 main 方法是 dart 的入口方法。runApp 方法是 flutter 的入口方法。 MyApp 是自定义的一个组件
=================================================================================
import ‘package:flutter/material.dart’;
void main() {
runApp(Center(
child: Text(
“我是一个文本内容”,
textDirection: TextDirection.ltr,
),
));
}
=======================================================================
在 Flutter 中自定义组件其实就是一个类,这个类需要继承 StatelessWidget/StatefulWidget
前期我们都继承 StatelessWidget。后期给大家讲 StatefulWidget 的使用。
StatelessWidget 是无状态组件,状态不可变的 widget
StatefulWidget 是有状态组件,持有的状态可能在 widget 生命周期改变
import ‘package:flutter/material.dart’;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
“我是一个文本内容”,
textDirection: TextDirection.ltr,
),
);
}
}
==========================================================================
import ‘package:flutter/material.dart’;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
“我是一个文本内容”,
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
// color: Colors.yellow
color: Color.fromRGBO(255, 222, 222, 0.5)
),
),
);
}
}
用MaterialApp 和 Scaffold两个组件装饰 App
============================================================================================
1、MaterialApp
MaterialApp 是一个方便的 Widget,它封装了应用程序实现 Material Design 所需要的 一些 Widget。一般作为顶层 widget 使用。
常用的属性:
home(主页)
title(标题)
color(颜色)
theme(主题)
routes(路由)
…
2、Scaffold
Scaffold 是 Material Design 布局结构的基本实现。此类提供了用于显示 drawer、snackbar 和底部 sheet 的 API。
Scaffold 有下面几个主要属性:
appBar - 显示在界面顶部的一个 AppBar。
body - 当前界面所显示的主要内容 Widget。
drawer - 抽屉菜单控件。
…
import ‘package:flutter/material.dart’;
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: “我是一个标题”,
home: Scaffold(
appBar: AppBar(
title: Text(“Hello Flutter”),
elevation: 30.0, 设置标题阴影 不需要的话值设置成 0.0
),
body: HomeContent(),
),
theme: ThemeData(
//设置主题颜色
primarySwatch: Colors.yellow),
);
}
}
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Text(
“我是一个文本内容”,
textDirection: TextDirection.ltr,
style: TextStyle(
fontSize: 40.0,
fontWeight: FontWeight.bold,
// color: Colors.yellow
color: Color.fromRGBO(255, 222, 222, 0.5)
),
),
);
}
}
==================================================================
| 名称 | 功能 |
| :-: | :-: |
| textAlign | 文本对齐方式(center 居中,left 左 对齐,right 右对齐,justfy 两端对齐) |
| textDirection | 文本方向(ltr 从左至右,rtl 从右至 左) |
| overflow | 文字超出屏幕之后的处理方式(clip 裁剪,fade 渐隐,ellipsis 省略号) |
| textScaleFactor | 字体显示倍率 |
| maxLines | 文字显示最大行数 |
| style | 字体的样式设置 |
下面是 TextStyle 的参数 :
| 名称 | 功能 |
| :-: | :-: |
| decoration | 文字装饰线(none 没有线,lineThrough 删 除线,overline 上划线,underline 下划线) |
| decorationColor | 文字装饰线颜色 |
| decorationStyle | 文字装饰线风格([dashed,dotted]虚线, double 两根线,solid 一根实线,wavy 波浪 线) |
| wordSpacing | 单词间隙(如果是负值,会让单词变得更紧 凑 |
| letterSpacing | 字母间隙(如果是负值,会让字母变得更紧 凑) |
| fontStyle | 文字样式(italic 斜体,normal 正常体) |
| fontSize | 文字大小 |
| color | 文字颜色 |
| fontWeight | 字体粗细(bold 粗体,normal 正常体) |
更多参数:https://docs.flutter.io/flutter/painting/TextStyle-class.html
=======================================================================
| 名称 | 功能 |
| :-: | :-: |
| alignment | topCenter:顶部居中对齐
topLeft:顶部左对齐
topRight:顶部右对齐
center:水平垂直居中对齐
centerLeft:垂直居中水平居左对齐
centerRight:垂直居中水平居右对齐
bottomCenter 底部居中对齐
bottomLeft:底部居左对齐
bottomRight:底部居右对齐 |
| decoration | decoration: BoxDecoration(
color: Colors.blue,
border: Border.all(
color: Colors.red,
width: 2.0,
),
borderRadius:
BorderRadius.all(
Radius.circular(8.0)
)
) |
| margin | margin 属性是表示 Container 与外部其他 组件的距离。
EdgeInsets.all(20.0), |
| padding | padding 就是 Container 的内边距,指 Container 边缘与 Child 之间的距离
padding: EdgeInsets.all(10.0) |
| transform | 让 Container 容易进行一些旋转之类的
transform: Matrix4.rotationZ(0.2) |
| height | 容器高度 |
| width | 容器宽度 |
| child | 容器子元素 |
更多参数:https://api.flutter.dev/flutter/widgets/Container-class.html
===============================================================
图片组件是显示图像的组件,Image 组件有很多构造函数,这里我们只给大家讲两个
Image.asset 本地图片
Image.network 远程图片
Image 组件的常用属性:
| 名称 | 类型 | 说明 |
| :-: | :-: | :-: |
| alignment | alignment | 图片的对齐方式 |
| color 和 colorBlendMode | | 设置图片的背景颜色,通常和 colorBlendMode 配合一起使用,这样可以是图片颜色和背景色混合。上面的图片就是进行了颜色的混合,绿色背景和图片红色的混合 |
| fit | BoxFit | fit 属性用来控制图片的拉伸和挤压,这都是根据父容器来的。
BoxFit.fill:全图显示,图片会被拉伸,并充满父容器。
BoxFit.contain:全图显示,显示原比例,可能会有空隙。
BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。
BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。
BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。
BoxFit.scaleDown:效果和 contain 差不多,但是此属性不允许显示超过源图片大小,可小不可大。 |
| repeat | 平铺 | ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布。
ImageRepeat.repeatX: 横向重复,纵向不重复。
ImageRepeat.repeatY:纵向重复,横向不重复。 |
| width | | 宽度 一般结合 ClipOval 才能看到效果 |
| height | | 高度 一般结合 ClipOval 才能看到效果 |
更多属性参考:https://api.flutter.dev/flutter/widgets/Image-class.html
return Center(
child: Container(
child: Image.network(
“http://pic.baike.soso.com/p/20130828/20130828161137-1346445960.jpg”,
alignment: Alignment.topLeft,
color: Colors.red,
colorBlendMode: BlendMode.colorDodge,
// repeat: ImageRepeat.repeatX,
fit: BoxFit.cover,
),
width: 300.0,
height: 400.0,
decoration: BoxDecoration(
color: Colors.yellow
),
),
);
=================================================================
emmm…不记了
裁剪布局之 ClipRect、ClipRRect、ClipOval、ClipPath、CustomClipper
===================================================================================================================
widget 作用
ClipRect 将 child 剪裁为给定的矩形大小
ClipRRect 将 child 剪裁为圆角矩形
ClipOval 如果 child 为正方形时剪裁之后是圆形,如果 child 为矩形时,剪裁之后为椭圆形
ClipPath 将 child 按照给定的路径进行裁剪
CustomClipper 并不是一个widget,但是使用CustomClipper可以绘制出任何我们想要的形状
=======================================================================
实现圆角图片
return Center(
child: Container(
width: 300.0,
height: 300.0,
decoration: BoxDecoration(
color: Colors.yellow,
borderRadius: BorderRadius.circular(150),
image: DecorationImage(
image: NetworkImage(
“http://pic.baike.soso.com/p/20130828/20130828161137-1346445960.jpg”,
),
fit: BoxFit.cover
)
),
),
);
实现圆形图片
return Center(
child: Container(
child: ClipOval(
child: Image.network(
“https://www.itying.com/images/201905/thumb_img/1101_thumb_G_1557845381862.jpg”,
width: 150.0,
height: 150.0,
),
),
),
);
ClipOval
new ClipOval(
child: new Image.asset(Utils.getImgPath(‘ali_connors’)),
)
② CircleAvatar
new CircleAvatar(
radius: 36.0,
backgroundImage: AssetImage(
Utils.getImgPath(‘ali_connors’),
),
)
③ BoxDecoration BoxShape.circle
new Container(
width: 72.0,
height: 72.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: AssetImage(
Utils.getImgPath(‘ali_connors’),
),
),
),
)
① ClipRRect
new ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: new Image.asset(Utils.getImgPath(‘ali_connors’)),
)
② BoxDecoration BoxShape.rectangle
new Container(
width: 88.0,
height: 88.0,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(6.0),
image: DecorationImage(
image: AssetImage(
Utils.getImgPath(‘ali_connors’),
),
),
),
=================================================================
列表布局是我们项目开发中最常用的一种布局方式。Flutter 中我们可以通过 ListView 来定义 列表项,支持垂直和水平方向展示。通过一个属性就可以控制列表的显示方向。列表有一下 分类:
**1、垂直列表(宽度自动扩展,设置宽度无效)**可以在外层包Container控制
2、垂直图文列表
**3、水平列表(高度自动扩展,设置高度无效)**可以在外层包Container控制
4、动态列表
5、矩阵式列表(网格布局)
===============================================================
| 名称 | 类型 | 说明 |
| :-: | :-: | :-: |
| scrollDirection | Axis | Axis.horizontal 水平列表
Axis.vertical 垂直列表 |
| padding | EdgeInsetsGeometry | 内边距 |
| resolve | bool | 组件反向排序 |
| children | List | 列表元素 |
===============================================================
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: ListView(
children: [
ListTile(
leading: Icon(Icons.phone),
title: Text(“this is list”, style: TextStyle(fontSize: 28.0)),
subtitle: Text(‘this is list this is list’),
),
ListTile(
title: Text(“this is list”),
subtitle: Text(‘this is list this is list’),
trailing: Icon(Icons.phone),
),
ListTile(
title: Text(“this is list”),
subtitle: Text(‘this is list this is list’),
),
ListTile(
title: Text(“this is list”),
subtitle: Text(‘this is list this is list’),
),
ListTile(
title: Text(“this is list”),
subtitle: Text(‘this is list this is list’),
)
],
),
);
}
}
===============================================================
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 200.0,
margin: EdgeInsets.all(5),
child: ListView(
scrollDirection: Axis.horizontal,
children: [
Container(
width: 180.0,
color: Colors.lightBlue,
),
Container(
width: 180,
color: Colors.amber,
child: ListView(
children: [
Image.network(
“https://resources.ninghao.org/images/childhood-in-a-picture.jpg”),
SizedBox(height: 16.0),
Text(“这是一个文本信息”,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 16.0)),
],
),
)
],
),
);
}
}
=======================================================================
import ‘package:flutter/material.dart’;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text(“Hello Flutter”)),
body: HomeContent(),
),
);
}
}
class HomeContent extends StatelessWidget {
List list = List();
HomeContent() {
for (int i = 0; i < 20; i++) {
list.add(“这是第$i条数据”);
}
print(list);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: this.list.length,
itemBuilder: (context, index) {
// print(context);
return ListTile(
leading: Icon(Icons.phone),
title: Text(“${list[index]}”),
);
});
}
}
===========================================================================
当数据量很大的时候用矩阵方式排列比较清晰。此时我们可以用网格列表组件 GridView 实现布局。
GridView 创建网格列表有多种方式,下面我们主要介绍两种。
1、可以通过 GridView.count 实现网格布局
2、通过 GridView.builder 实现网格布局
常用属性:
| 名称 | 类型 | 说明 |
| :-: | :-: | :-: |
| scrollDirection | Axis | 滚动方法 |
| padding | EdgeInsetsGeometry | 内边距 |
| resolve | bool | 组件反向排序 |
| crossAxisSpacing | double | 水平子 Widget 之间间距 |
| mainAxisSpacing | double | 垂直子 Widget 之间间距 |
| crossAxisCount | int | 一行的 Widget 数量 |
| childAspectRatio | double | 子 Widget 宽高比例 |
| children | | [ ] |
| gridDelegate | **SliverGridDelegateWithFix
edCrossAxisCount(常用)
SliverGridDelegateWithMax
CrossAxisExtent** | 控制布局主要用在GridView.builder 里面 |
================================================================================
import ‘package:cc/res/listData.dart’;
import ‘package:flutter/material.dart’;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: T