Path的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

/// rect 圆弧所在的矩形
/// startAngle 初始化弧度
/// sweepAngle 需要绘制的弧度大小
/// forceMoveTo 是否强制连线
void arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo) {
}



class ArcWidget extends StatefulWidget {
const ArcWidget({super.key});

@override
State<ArcWidget> createState() => _ArcWidgetState();
}

class _ArcWidgetState extends State<ArcWidget> {
@override
Widget build(BuildContext context) {
return Container(
height: 50.h,
child: CustomPaint(
painter: ArcPainter(),
child: Container(),
),
);
}
}

class ArcPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final paint = Paint()
..color = Colors.white
..style = PaintingStyle.fill;

final path = Path()
..moveTo(0, size.height + 1) // Start at the bottom-left corner
..lineTo(0, size.height - 10.h) // Move up by 100 pixels
..quadraticBezierTo(size.width / 2, size.height - 48.h, size.width, size.height - 10.h) // Draw a quadratic bezier curve
..lineTo(size.width, size.height + 1) // Draw a line to the bottom-right corner
..close(); // Close the path

canvas.drawPath(path, paint);
}

@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}


ES6

Babel 转码器

Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码,从而在老版本的浏览器执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持。下面是一个例子

1
2
3
4
5
6
7
8
// 转码前
input.map(item => item + 1);

// 转码后
input.map(function (item) {
return item + 1;
});

let 和 const 命令

ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效

Read More

常用开源库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116


# 处理model,用于自动生成对应实体类
json_annotation:
json_serializable:

# 设备信息、包信息
package_info_plus:
device_info_plus:

# 下拉、上拉刷新
easy_refresh:

# 吐司提示
fluttertoast:

# 模态提示
flutter_easyloading: 3.0.5

# 音频处理
just_audio:
audio_session:
flutter_sound:

# Reactive dart实现
rxdart:

# 数据库操作
sqflite:

# 网络请求
dio:

# 加解密
encrypt:

# 缓存
shared_preferences:

# 图片扩展库、缓存图片
extended_image:

# 强大的工具包,支持路由、状态管理等
get:

# 屏幕适配方案
flutter_screenutil:

# 左滑删除
flutter_slidable:

# 苹果登录
sign_in_with_apple:

# 可滑动展示的控件、轮播图
card_swiper:


# 增强版文字控件
extended_text_field:

# 浏览器容器
webview_flutter:


# 权限管理
permission_handler:

# 系统文件选择
file_picker:

# 系统图片选择
image_picker:

#svg控件
flutter_svg:

# 支持svga控件
svgaplayer_flutter:

# 支持打开各种格式的文件
open_file:


# 强大的状态管理框架
flutter_bloc:

# 剪切板工具
clipboard:

# 事件总线工具
event_bus:

# 支持lottie动画
lottie:

# 异常捕获
sentry_flutter:

# 开发调试框架
flutter_ume:

# 各种路径的封装,比如临时目录、缓存目录
path_provider:

# 外部浏览器打开url
url_launcher:

# 系统分享组件
share_plus:

# 实体类工具,快捷生成model
freezed:

# 视频播放
video_player:

参考

Read More

bloc_test

创建Mock

1
2
3
4
import 'package:bloc_test/bloc_test.dart';

class MockCounterBloc extends MockBloc<CounterEvent, int> implements CounterBloc {}
class MockCounterCubit extends MockCubit<int> implements CounterCubit {}

blocTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void blocTest<B extends BlocBase<State>, State>(
String description, { //测试的描述
required B Function() build, //创建bloc
FutureOr<void> Function()? setUp, //在每个测试用例执行前执行
State Function()? seed,
dynamic Function(B bloc)? act, //执行的动作
Duration? wait,
int skip = 0,
dynamic Function()? expect, //期望的结果
dynamic Function(B bloc)? verify,
dynamic Function()? errors,
FutureOr<void> Function()? tearDown, //在每个测试用例执行后执行
dynamic tags,
})

参数

Read More

集成测试

integration_test

集成测试框架,可分析测试用例的性能指标

官方文档:https://flutter.cn/docs/cookbook/testing/integration/introduction

基本使用

1. 添加配置

1
2
3
4
5
6
7
8
9
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^1.0.0
mockito:
integration_test:
sdk: flutter
flutter_driver:
sdk: flutter

2. 根目录下新建test_driver文件夹,编写integration_test.dart文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import 'dart:io';
import 'package:integration_test/integration_test_driver_extended.dart';

Future<void> main() => integrationDriver(
onScreenshot: (String screenshotPath, List<int> screenshotBytes) async {

final File image = File(screenshotPath);
final dir = image.parent;
print(image);

if(!await dir.exists()) await dir.create(recursive: true);
image.writeAsBytesSync(screenshotBytes);

return true;

}
);

Read More