12.7 tag 分组组件 编写

12.7 tag 分组组件 编写

image-20220722093724351

实现步骤:


第 1 步:tag 分组组件

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

import '../index.dart';

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

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

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

// 宽
final double? width;

// 高
final double? height;

// 文字颜色
final Color? textColor;

// 文字选中颜色
final Color? textSelectedColor;

// 文字尺寸
final double? textSize;

// 文字 weight
final FontWeight? textWeight;

// 背景颜色
final Color? bgColor;

// 选中背景颜色
final Color? bgSelectedColor;

// 圆角
final double? borderRadius;

// 元素间距
final double? spacing;

// 行间距
final double? runSpacing;

// 是否圆形
final bool? isCircular;

// 尺寸
final double? size;

// 构造
TagsListWidget({
Key? key,
this.onTap,
required this.itemList,
required this.keys,
Color? bgColor,
Color? bgSelectedColor,
Color? textColor,
Color? textSelectedColor,
this.spacing,
this.runSpacing,
this.width = 50,
this.height = 30,
this.borderRadius = 3,
this.textSize,
this.textWeight,
this.isCircular = false,
this.size,
}) : bgColor = bgColor ?? AppColors.surfaceVariant,
bgSelectedColor = bgSelectedColor ?? AppColors.primary,
textColor = textColor ?? AppColors.secondary,
textSelectedColor = textSelectedColor ?? AppColors.onPrimary,
super(key: key);

@override
Widget build(BuildContext context) {
return <Widget>[
for (var item in itemList)
SizedBox(
width: size ?? width,
height: size ?? height,
child: TextWidget.body2(
item.value.name ?? "",
color:
keys.hasValue(item.key) == true ? textSelectedColor : textColor,
textAlign: TextAlign.center,
weight: textWeight ?? FontWeight.bold,
size: textSize,
)
.center()
// 装饰器
.decorated(
// 背景
color:
keys.hasValue(item.key) == true ? bgSelectedColor : bgColor,
// 圆角
borderRadius: BorderRadius.circular(
isCircular == true ? size ?? 24 : borderRadius ?? 3),
)
// 点击
.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,
);
}
}

第 2 步:商品首页缓存尺寸定义

lib/common/values/constants.dart

1
2
// 尺寸定义
static const storageProductsAttributesSizes = 'products_attributes_sizes';

lib/pages/goods/home/controller.dart

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

// 保存离线数据
// 尺寸定义
Storage().setJson(Constants.storageProductsAttributesSizes, attributeSizes);

...

第 3 步:控制器

lib/pages/goods/product_details/controller.dart

1
2
3
4
// 尺寸列表
List<KeyValueModel<AttributeModel>> sizes = [];
// 选中尺寸列表
List<String> sizeKeys = [];
1
2
3
4
5
6
7
8
9
10
11
12
13
// 读取缓存
_loadCache() async {
// 尺寸列表
var stringSizes =
Storage().getString(Constants.storageProductsAttributesSizes);

sizes = stringSizes != ""
? jsonDecode(stringSizes).map<KeyValueModel<AttributeModel>>((item) {
var arrt = AttributeModel.fromJson(item);
return KeyValueModel(key: "${arrt.name}", value: arrt);
}).toList()
: [];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  // 拉取商品详情_
loadProduct() async {
// 商品详情
...

// 选中值
if (product?.attributes != null) {
// 颜色
var colorAttr = product?.attributes?.where((e) => e.name == "Color");
if (colorAttr?.isNotEmpty == true) {
colorKeys = colorAttr?.first.options ?? [];
}
// 尺寸
var sizeAttr = product?.attributes?.where((e) => e.name == "Size");
if (sizeAttr?.isNotEmpty == true) {
sizeKeys = sizeAttr?.first.options ?? [];
}
}
...

初始默认颜色、尺寸

1
2
3
4
5
6
// 尺寸选中
void onSizeTap(List<String> keys) {
sizeKeys = keys;
update(["product_sizes"]);
}

第 4 步:商品规格子组件视图

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@override
Widget build(BuildContext context) {
return <Widget>[
...

// 尺寸
_buildTitle("Size"),
GetBuilder<ProductDetailsController>(
id: "product_sizes",
tag: uniqueTag,
builder: (_) {
return TagsListWidget(
itemList: controller.sizes,
keys: controller.sizeKeys,
onTap: controller.onSizeTap,
).paddingBottom(AppSpace.listRow * 2);
},
),

...

提交代码到 git