3.4 图标组件封装

3.4 图标组件封装

图标组件封装,实现步骤:


第 1 步:安装依赖包 flutter_svg badges

1
2
flutter pub add flutter_svg
flutter pub add badges

最近的几个项目都在用 svg 图标了,这种图标颜色更丰富些,你可以传统 iconData 加 svg 组合在项目中使用

第 2 步:IconWidget 封装

定义如下

name 说明 参数
icon Icons 图标 iconData 图标数据
svg svg 文件路径 assetName svg 文件
image asset 图片路径 assetName 图片文件
url url 网址 来自网络图标

lib/common/widgets/icon.dart

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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
import 'package:badges/badges.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

import '../index.dart';

enum IconWidgetType { icon, svg, image, url }

/// 图标组件
class IconWidget extends StatelessWidget {
/// 图标类型
final IconWidgetType type;

/// 图标数据
final IconData? iconData;

/// assets 路径
final String? assetName;

/// 图片 url
final String? imageUrl;

/// 尺寸
final double? size;

///
final double? width;

///
final double? height;

/// 颜色
final Color? color;

/// 是否小圆点
final bool? isDot;

/// Badge 文字
final String? badgeString;

/// 图片 fit
final BoxFit? fit;

const IconWidget({
Key? key,
this.type = IconWidgetType.icon,
this.size,
this.width,
this.height,
this.color,
this.iconData,
this.isDot,
this.badgeString,
this.assetName,
this.imageUrl,
this.fit,
}) : super(key: key);

IconWidget.icon(
this.iconData, {
Key? key,
this.type = IconWidgetType.icon,
this.size = 24,
this.width,
this.height,
this.color,
this.isDot,
this.badgeString,
this.assetName,
this.imageUrl,
this.fit,
}) : super(key: key) {
return;
}

IconWidget.image(
this.assetName, {
Key? key,
this.type = IconWidgetType.image,
this.size = 24,
this.width,
this.height,
this.color,
this.iconData,
this.isDot,
this.badgeString,
this.imageUrl,
this.fit,
}) : super(key: key) {
return;
}

IconWidget.svg(
this.assetName, {
Key? key,
this.type = IconWidgetType.svg,
this.size = 24,
this.width,
this.height,
this.color,
this.iconData,
this.isDot,
this.badgeString,
this.imageUrl,
this.fit,
}) : super(key: key) {
return;
}

IconWidget.url(
this.imageUrl, {
Key? key,
this.type = IconWidgetType.url,
this.size = 24,
this.width,
this.height,
this.color,
this.iconData,
this.isDot,
this.badgeString,
this.assetName,
this.fit,
}) : super(key: key) {
return;
}

@override
Widget build(BuildContext context) {
Widget? icon;
switch (type) {
case IconWidgetType.icon:
icon = Icon(
iconData,
size: size,
color: color ?? AppColors.primary,
);
break;
case IconWidgetType.svg:
icon = SvgPicture.asset(
assetName!,
width: width ?? size,
height: height ?? size,
color: color,
fit: fit ?? BoxFit.contain,
);
break;
case IconWidgetType.image:
icon = Image.asset(
assetName!,
width: width ?? size,
height: height ?? size,
color: color,
fit: fit ?? BoxFit.contain,
);
break;
case IconWidgetType.url:
icon = Image.network(
imageUrl!,
width: width ?? size,
height: height ?? size,
color: color,
fit: fit ?? BoxFit.contain,
);
break;
default:
return const SizedBox();
}

// 圆点
if (isDot == true) {
return Badge(
position: BadgePosition.bottomEnd(bottom: 0, end: -2),
elevation: 0,
badgeColor: AppColors.primary,
padding: const EdgeInsets.all(4.0),
child: icon,
);
}

// 文字、数字
if (badgeString != null) {
return Badge(
badgeContent: Text(
badgeString!,
style: TextStyle(
color: AppColors.onPrimary,
fontSize: 9,
),
),
position: BadgePosition.topEnd(top: -7, end: -8),
elevation: 0,
badgeColor: AppColors.primary,
padding: const EdgeInsets.all(4.0),
child: icon,
);
}

// 图标
return icon;
}
}

第 3 步:icon 调试界面

lib/pages/styles/styles_index/view.dart

1
2
3
4
5
// Icon 图标
ListTile(
onTap: () => Get.toNamed(RouteNames.stylesIcon),
title: const TextWidget.body1("Icon 图标"),
),

lib/pages/styles/icon/view.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Widget _buildView() {
return ListView(
children: [
ListTile(
leading: IconWidget.icon(Icons.home),
title: const TextWidget.body1("IconWidget.icon"),
),
ListTile(
leading: IconWidget.image(AssetsImages.defaultPng),
title: const TextWidget.body1("IconWidget.image"),
),
ListTile(
leading: IconWidget.svg(AssetsSvgs.cHomeSvg),
title: const TextWidget.body1("IconWidget.svg"),
),
ListTile(
leading: IconWidget.url(
"https://ducafecat.oss-cn-beijing.aliyuncs.com/flutter_woo_commerce_getx_ducafecat/categories/c-man.png"),
title: const TextWidget.body1("IconWidget.url"),
),
],
);
}

最后:运行

分别支持 iconData image svg url 4 种方式创建图标

image-20220708155630350

提交代码到 git