在使用组件库Bruno的BrnSelectTag组件时,发现以下问题:
在当一个页面多次使用该组件时,在滚动页面的时候,选中的tag会莫名其妙在页面上变成未选中的状态。故重新写了一个SelectTag组件,来满足业务要求。
一、SelectTag组件主要的属性:
- isSingle默认false,为多选,单选为true;
- tagList支持的数据结构
[{'label':'测试','select':false}]
; - onSelect选中回调的方法,默认返回选中的项的下标index;
- 如果需要默认选中某项,把tagList中需要选中项的属性select改成true;
二、组件效果
三、组件使用代码:
import 'package:flutter/material.dart';
import 'package:k6mobile/components/selectTag/index.dart';
class StartMachinePage extends StatefulWidget {
const StartMachinePage({Key? key}) : super(key: key);
State<StartMachinePage> createState() => _StartMachinePageState();
}
class _StartMachinePageState extends State<StartMachinePage> {
List tagList = [
{'label': '选项一', 'select': false},
{'label': '选项二', 'select': false},
{'label': '选项三不规则展示项', 'select': false},
{'label': '不规则展示项四', 'select': false},
{'label': '不规则展示五', 'select': false},
{'label': '不规则展示项六', 'select': false},
{'label': '不规则展示项七', 'select': false},
{'label': '选项一', 'select': false},
{'label': '选项二', 'select': false},
{'label': '选项一', 'select': false},
{'label': '选项二', 'select': false},
];
Map chooseItem = {};
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: new BoxDecoration(
color: Color(0xFFffffff),
),
padding: EdgeInsets.only(
top: 80,
bottom: 5,
right: 10,
left: 15,
),
child: Container(
child: SelectTag(
tagList: tagList,
isSingle: false,
onSelect: (selectedIndexes){
chooseItem = tagList[selectedIndexes];
}))));
}
}
四、组件完整代码:
import 'package:flutter/material.dart';
class SelectTag extends StatefulWidget {
// tag组件数据eg:['label':'测试','select':false]
final List<dynamic> tagList;
// 返回选中 tag 的下标
final void Function(dynamic)? onSelect;
// 是否单选,默认多选
final bool isSingle;
const SelectTag(
{Key? key, required this.tagList, this.onSelect, this.isSingle = false})
: super(key: key);
State<SelectTag> createState() => _SelectTagState();
}
class _SelectTagState extends State<SelectTag> {
//计算Text的内容宽度
double calculateTextWidth(String text, TextStyle style) {
TextPainter textPainter = TextPainter(
text: TextSpan(text: text, style: style),
textDirection: TextDirection.ltr,
);
textPainter.layout();
return textPainter.size.width;
}
Widget build(BuildContext context) {
return Container(alignment: Alignment.topLeft, child: buildPackItem());
}
buildPackItem() {
Widget itemContent;
List<Widget> children = []; // 创建一个列表来存储子元素
// 使用for循环遍历widget.tagList
for (var i = 0; i < widget.tagList.length; i++) {
var item = widget.tagList[i]; // 获取当前元素
Widget childWidget = Container(
padding: EdgeInsets.only(
top: 5,
bottom: 5,
right:10
),
child: Container(
child: Row(
mainAxisSize: MainAxisSize.min,
// 使用当前元素的索引i作为pickPoint的第二个参数
children: [pickPoint(item, i)], // 假设pickPoint的第二个参数从1开始
),
),
);
children.add(childWidget); // 将构建的子元素添加到列表中
}
// 使用Wrap来包裹所有子元素
itemContent = Wrap(
children: children,
);
return itemContent;
}
pickPoint(item, index) {
//计算Text内容宽度
double textWidth = calculateTextWidth(
item['label'],
TextStyle(
fontWeight: item['select'] ? FontWeight.bold : FontWeight.normal,
color: item['select'] ? Color(0xFF0984f9) : Color(0xFF2c2c2c),
fontSize: 12,
));
//计算屏幕宽度
double screenWidth = MediaQuery.of(context).size.width;
return Container(
child: Column(
children: [
InkWell(
onTap: () {
setState(() {
if (widget.isSingle) {
List tagList = widget.tagList;
for (int i = 0; i < tagList.length; i++) {
if (i == index) {
tagList[i]['select'] = true;
} else {
tagList[i]['select'] = false;
}
}
} else {
item['select'] = !item['select'];
}
});
if (widget.onSelect != null) {
widget.onSelect!(index);
}
},
child: Container(
constraints: BoxConstraints(
minWidth: 90,
minHeight: 34,
),
padding: EdgeInsets.only(
left: 5,
right: 5,
),
decoration: new BoxDecoration(
color: item['select'] ? Color(0xFFe1f0fe) : Color(0xFFf8f8f8),
),
alignment: Alignment.center,
child: Container(
width: textWidth > screenWidth - 45
? screenWidth - 45
: textWidth,
child: Text(item['label'],
style: TextStyle(
fontWeight: item['select']
? FontWeight.bold
: FontWeight.normal,
color: item['select']
? Color(0xFF0984f9)
: Color(0xFF2c2c2c),
fontSize: 11,
),
softWrap: true),
)))
],
));
}
}