12.6 颜色分组组件编写

12.6 颜色分组组件编写

image-20220722092648351

实现步骤:


第 1 步:离线缓存常量

lib/common/values/constants.dart

1
2
// 颜色定义
static const storageProductsAttributesColors = 'products_attributes_colors';

第 2 步:定义模型

img

slug 是颜色值
name 是显示的名称

生成定义json to dart

lib/common/models/woo/attribute_model/attribute_model.dart

img

第 3 步:API 定义

image-20220722091657906

lib/common/api/product.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/// 属性列表
/// id 1 颜色 2 尺寸
static Future<List<AttributeModel>> attributes(int id) async {
var res = await WPHttpService.to.get(
'/products/attributes/$id/terms',
);

List<AttributeModel> attributes = [];
for (var item in res.data) {
attributes.add(AttributeModel.fromJson(item));
}
// 排序 menuOrder , 小号在前
attributes.sort((a, b) => a.menuOrder!.compareTo(b.menuOrder as int));
return attributes;
}

第 4 步:拉取颜色定义

我们再商品首页拉取数据并缓存

lib/pages/goods/home/controller.dart

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 初始数据,从网络拉取
Future<void> _initData() async {
// 基础数据
...
// 颜色
var attributeColors = await ProductApi.attributes(1);

// 保存离线数据
// 基础
Storage().setJson(Constants.storageProductsAttributesColors, attributeColors);

...

update(["home"]);
}

第 5 步:颜色分组组件编写

lib/common/components/colors_list.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
import 'package:flutter/material.dart';

import '../index.dart';

/// 颜色列表组件
class ColorsListWidget extends StatelessWidget {
// 点击事件
final Function(List<String> keys)? onTap;

// 颜色列表
final List<KeyValueModel<AttributeModel>> itemList;

// 选中的颜色
final List<String> keys;

// 单个尺寸
final double? size;

// 边框颜色
final Color? borderSelectedColor;

// 元素间距
final double? spacing;

// 行间距
final double? runSpacing;

// 构造
const ColorsListWidget({
Key? key,
this.onTap,
required this.itemList,
required this.keys,
this.size,
this.spacing,
this.runSpacing,
this.borderSelectedColor,
}) : super(key: key);

@override
Widget build(BuildContext context) {
return <Widget>[
for (var item in itemList)
SizedBox(
width: size ?? 24,
height: size ?? 24,
)
// 装饰器
.decorated(
// 背景
color: item.value.slug?.toColor,
// 边框
border: keys.hasValue(item.key) == true
? Border.all(
color: borderSelectedColor ?? AppColors.highlight,
width: 2,
)
: null,
// 圆角
borderRadius: BorderRadius.circular(size ?? 12),
)
// 紧约束
.tight(width: size, height: size)
// 点击
.onTap(() {
if (keys.hasValue(item.key)) {
keys.remove(item.key);
} else {
keys.add(item.key);
}
onTap?.call(keys);
})
].toWrap(
spacing: spacing ?? AppSpace.listItem,
runSpacing: runSpacing ?? AppSpace.listRow,
);
}
}

第 6 步: 控制器 - 读取缓存

lib/pages/goods/product_details/controller.dart

1
2
3
4
// 颜色列表
List<KeyValueModel<AttributeModel>> colors = [];
// 选中颜色列表
List<String> colorKeys = [];
1
2
3
4
5
6
7
8
9
10
11
12
13
// 读取缓存
_loadCache() async {
// 颜色列表
var stringColors =
Storage().getString(Constants.storageProductsAttributesColors);

colors = stringColors != ""
? jsonDecode(stringColors).map<KeyValueModel<AttributeModel>>((item) {
var arrt = AttributeModel.fromJson(item);
return KeyValueModel(key: "${arrt.name}", value: arrt);
}).toList()
: [];
}
1
2
3
4
5
// 颜色选中
void onColorTap(List<String> keys) {
colorKeys = keys;
update(["product_colors"]);
}
1
2
3
4
_initData() async {
await _loadCache();
...
}

第 7 步:视图 - 规格页使用

lib/pages/goods/product_details/widgets/tab_product.dart

1
2
3
4
// 标题
_buildTitle(String title) {
return TextWidget.body1(title).paddingBottom(AppSpace.listRow);
}
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
@override
Widget build(BuildContext context) {
return <Widget>[
...

// 颜色
_buildTitle("Color"),
GetBuilder<ProductDetailsController>(
id: "product_colors",
tag: uniqueTag,
builder: (_) {
return ColorsListWidget(
itemList: controller.colors,
keys: controller.colorKeys,
size: 33.w,
onTap: controller.onColorTap,
).paddingBottom(AppSpace.listRow * 2);
},
),
]
.toColumn(
crossAxisAlignment: CrossAxisAlignment.start,
)
.paddingVertical(AppSpace.page);

...
}

提交代码到 git