键盘弹起导致TextField背景色更新不及时,要键盘收起才更新

文章介绍了在Flutter项目中如何根据后端数据动态生成检查卡片,特别是如何使用ValueListenableBuilder来实现实时更新结果判定TextField的内容和背景色。当检查结果变化时,通过改变ValueNotifier的值触发组件局部更新,从而避免键盘收起后才更新背景色的问题。
摘要由CSDN通过智能技术生成

问题描述:

        近期Flutter项目有个需求,根据后端传过来的数据,动态生成检查项目卡片,卡片中动态生成5个检查结果录入的TextField和一个结果判定的TextField,结果判定的TextField中的内容根据5个检查结果自动判定OK和NG,并将OK背景色设置为绿色,NG背景色设置为红色。但是,根据5个检查结果通过setState更新结果判定的TextField中的文本,内容更新后,背景色要键盘收起才会更新。

解决方案:

使用局部更新组件:ValueListenableBuilder 

1、组件使用方式:

a、通过ValueNotifier设置变量changeFlag,ValueListenableBuilder通过观测此变量,一旦变量内容发生变化,则刷新对应的组件

final ValueNotifier<int> count = ValueNotifier<int>(0);

b、使用官方的 ValueListenableBuilder 组件进行包裹你需要更新状态的组件。它有两个参数,一个是监听的值,一个是渲染的组件,当这个值发生改变,就可以重新触发渲染组件的函数

ValueListenableBuilder(
    valueListenable: changeFlag,
    builder: (context, value, widget) {
    return 组件;
},
)

c、改变changeFlag来更新组件

void _refreshComponent() {
    changeFlag.value++;
}

2、项目实例:

a、初始化项目对象

List<Map<String, dynamic>> checkItem = [];

b、在initState中给checkItem赋值,实际项目从后端获取数据

@override
void initState() {
  // TODO: implement initState
  super.initState();

  checkItem.add(
    {
      "insItem": "项目名称",
      "insCondition": "检查规格",
      "max": "10",//规格上限
      "min": "0",//规格下限
      "insUnit": "测量单位",
      //五个检查录入格子控制器
      "textEditControllers": [
        new TextEditingController(),
        new TextEditingController(),
        new TextEditingController(),
        new TextEditingController(),
        new TextEditingController(),
      ],
      //五个检查录入格子的状态,用来推断OK/NG
      "textEditStatus": [
        false,
        false,
        false,
        false,
        false,
      ],
      //五个检查录入格子焦点
      "focusNodes": [
        new FocusNode(),
        new FocusNode(),
        new FocusNode(),
        new FocusNode(),
        new FocusNode(),
      ],
      //判定格子的控制器
      "judgeController": new TextEditingController(),
      //通过来回切换true/false来触发组件刷新,防止键盘弹起时无法即使更新TextField的背景色
      "refresh": ValueNotifier<bool>(true)
    },
  );

  lastFocusNode = checkItem[2]["focusNodes"][4];
}

c、在dispose中释放focus

@override
void dispose() {
  for (var item in checkItem) {
    for (var focusNode in item["focusNodes"]) {
      focusNode.dispose();
    }
  }
  super.dispose();
}

d、组件使用

ValueListenableBuilder(
    valueListenable: item["refresh"],
    builder: (context, value, widget) {
      return Row(
        children: [
          Text(
            "判定:",
            style: TextStyle(
              fontSize: fontSize,
            ),
          ),
          Expanded(
            child: TextField(
              textAlign: TextAlign.center,
              decoration: InputDecoration(
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(15.0),
                ),
                fillColor: item["judgeController"].text == "NG"
                    ? Colors.red
                    : item["judgeController"].text == "OK"
                        ? Color.fromRGBO(103, 194, 58, 1)
                        : Colors.white,
                filled: true,//要使背景色生效必须设置为true
              ),
              style: TextStyle(
                fontSize: fontSize,
              ),
              controller: item["judgeController"],
              enabled: false,
            ),
          ),
          Expanded(
            child: Container(),
            flex: 4,
          )
        ],
      );
    })

/// description 根据检查结果修改判定状态
/// author JackMa
/// Date 2023/7/10 10:26
changeStatus(var item, setInnerState) {
  //是否有异常
  bool flag = false;
  for (int i = 0; i < item["textEditStatus"].length; i++) {
    if (item["textEditStatus"][i]) {
      setInnerState(() {
        item["judgeController"].text = "NG";
        item["refresh"].value = !item["refresh"].value;
      });
      flag = true;
      break;
    }
  }
  if (!flag) {
    //是否有空的判定格子
    bool hasEmpty = false;
    for (int i = 0; i < item["textEditControllers"].length; i++) {
      if (item["textEditControllers"][i].text == "") {
        setInnerState(() {
          item["judgeController"].text = "";
          item["refresh"].value = !item["refresh"].value;
        });
        hasEmpty = true;
        break;
      }
    }
    if (!hasEmpty) {
      setInnerState(() {
        item["judgeController"].text = "OK";
        item["refresh"].value = !item["refresh"].value;
      });
    }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值