Flutter组件—SelectTag选择组件

在使用组件库BrunoBrnSelectTag组件时,发现以下问题:
在当一个页面多次使用该组件时,在滚动页面的时候,选中的tag会莫名其妙在页面上变成未选中的状态。故重新写了一个SelectTag组件,来满足业务要求。

一、SelectTag组件主要的属性:

  1. isSingle默认false,为多选,单选为true;
  2. tagList支持的数据结构[{'label':'测试','select':false}]
  3. onSelect选中回调的方法,默认返回选中的项的下标index;
  4. 如果需要默认选中某项,把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),
                )))
      ],
    ));
  }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值