You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter实现SI单位双向转换及TextField输入处理技术问询

解决Flutter单位转换应用的双向转换与条件判断问题

Hey Lakshan, 我来帮你搞定这个单位转换应用的问题!咱们一步步来实现你要的双向转换功能,同时把Flutter里的条件判断用法也讲明白。

首先,我先梳理下你的需求:两个输入框对应不同单位,输入其中一个时自动转换到另一个;支持双向同步;还要学会Flutter里的条件判断逻辑。接下来咱们逐个解决这些问题。

一、先调整基础结构:添加双输入控制器

你现在只有一个控制器,我们需要给两个输入框各配一个控制器,这样才能分别监听和修改它们的内容。另外,要注意Dropdown里的单位值大小写要统一(比如你之前的"Kilogram"和"kilogram"会导致匹配错误),我已经帮你统一成小写了。

二、编写单位转换函数(核心:条件判断的用法)

这里我们用if-else或者switch-case来处理不同单位之间的转换逻辑,这就是Flutter里常用的条件判断方式。比如千克和克的转换,我们可以这样写:

double convertUnit(double input, String fromUnit, String toUnit) {
  if (fromUnit == toUnit) return input; // 相同单位直接返回原值

  // 千克与克之间的转换
  if (fromUnit == "kilogram" && toUnit == "gram") {
    return input * 1000;
  } else if (fromUnit == "gram" && toUnit == "kilogram") {
    return input / 1000;
  }

  // 以后可以在这里添加更多单位的转换逻辑,比如磅、盎司等
  return input;
}

如果单位类型多,也可以用switch-case来让代码更清晰:

double convertUnit(double input, String fromUnit, String toUnit) {
  if (fromUnit == toUnit) return input;

  switch('$fromUnit-$toUnit') {
    case 'kilogram-gram':
      return input * 1000;
    case 'gram-kilogram':
      return input / 1000;
    // 其他单位组合的case
    default:
      return input;
  }
}

三、实现双向输入同步

我们需要给两个控制器添加监听事件,当其中一个输入框的内容变化时,自动计算并更新另一个输入框的内容。还要加个标记避免循环触发(比如A更新B,B又触发更新A)。

四、完整修改后的代码

下面是整合了所有功能的完整代码,每部分都加了注释:

class Weight extends StatefulWidget {
  @override
  _WeightState createState() => _WeightState();
}

class _WeightState extends State<Weight> {
  String? _value1; // 第一个单位(比如kilogram)
  String? _value2; // 第二个单位(比如gram)
  final TextEditingController _controller1 = TextEditingController(); // 第一个输入框控制器
  final TextEditingController _controller2 = TextEditingController(); // 第二个输入框控制器
  bool _isUpdating = false; // 避免循环更新的标记

  @override
  void initState() {
    super.initState();
    // 监听第一个输入框的变化
    _controller1.addListener(_onInput1Changed);
    // 监听第二个输入框的变化
    _controller2.addListener(_onInput2Changed);
  }

  @override
  void dispose() {
    // 记得销毁控制器,避免内存泄漏
    _controller1.dispose();
    _controller2.dispose();
    super.dispose();
  }

  // 处理第一个输入框的变化,转换后更新第二个输入框
  void _onInput1Changed() {
    if (_isUpdating || _value1 == null || _value2 == null) return;
    final input = double.tryParse(_controller1.text);
    if (input == null) {
      _controller2.clear();
      return;
    }
    final result = convertUnit(input, _value1!, _value2!);
    _isUpdating = true;
    _controller2.text = result.toStringAsFixed(2); // 保留两位小数
    _isUpdating = false;
  }

  // 处理第二个输入框的变化,转换后更新第一个输入框
  void _onInput2Changed() {
    if (_isUpdating || _value1 == null || _value2 == null) return;
    final input = double.tryParse(_controller2.text);
    if (input == null) {
      _controller1.clear();
      return;
    }
    final result = convertUnit(input, _value2!, _value1!);
    _isUpdating = true;
    _controller1.text = result.toStringAsFixed(2);
    _isUpdating = false;
  }

  // 单位转换核心函数,包含条件判断
  double convertUnit(double input, String fromUnit, String toUnit) {
    if (fromUnit == toUnit) return input;

    // 千克和克的转换逻辑
    if (fromUnit == "kilogram" && toUnit == "gram") {
      return input * 1000;
    } else if (fromUnit == "gram" && toUnit == "kilogram") {
      return input / 1000;
    }

    // 后续可以添加更多单位,比如:
    // if (fromUnit == "kilogram" && toUnit == "pound") {
    //   return input * 2.20462;
    // }

    return input;
  }

  @override
  Widget build(BuildContext context) {
    return Material(
      child: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 20),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              // 第一个单位选择器
              DropdownButton<String>(
                items: const [
                  DropdownMenuItem(child: Text("Kilogram"), value: "kilogram"),
                  DropdownMenuItem(child: Text("Gram"), value: "gram"),
                ],
                onChanged: (String? value) {
                  setState(() {
                    _value1 = value;
                    // 单位切换后,重新触发转换
                    _onInput1Changed();
                  });
                },
                hint: const Text('Select Unit'),
                value: _value1,
                isExpanded: true, // 让下拉框占满宽度
              ),
              const SizedBox(height: 10),
              // 第一个输入框
              TextField(
                controller: _controller1,
                keyboardType: TextInputType.numberWithOptions(decimal: true),
                decoration: InputDecoration(
                  border: const OutlineInputBorder(),
                  labelText: _value1 != null ? "Enter amount in $_value1" : "Enter amount",
                ),
              ),
              const SizedBox(height: 50),
              // 第二个单位选择器
              DropdownButton<String>(
                items: const [
                  DropdownMenuItem(child: Text("Kilogram"), value: "kilogram"),
                  DropdownMenuItem(child: Text("Gram"), value: "gram"),
                ],
                onChanged: (String? value) {
                  setState(() {
                    _value2 = value;
                    // 单位切换后,重新触发转换
                    _onInput2Changed();
                  });
                },
                hint: const Text('Select Unit'),
                value: _value2,
                isExpanded: true,
              ),
              const SizedBox(height: 10),
              // 第二个输入框
              TextField(
                controller: _controller2,
                keyboardType: TextInputType.numberWithOptions(decimal: true),
                decoration: InputDecoration(
                  border: const OutlineInputBorder(),
                  labelText: _value2 != null ? "Enter amount in $_value2" : "Enter amount",
                ),
              ),
              const SizedBox(height: 50),
              // 转换按钮(其实现在已经自动转换了,按钮可以保留用来手动触发或者扩展功能)
              ElevatedButton(
                onPressed: () {
                  // 手动触发转换的话,可以调用_onInput1Changed()或者_onInput2Changed()
                  _onInput1Changed();
                },
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.all(12),
                  elevation: 15,
                ),
                child: const Text(
                  "Convert",
                  style: TextStyle(fontSize: 25, color: Colors.black),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

关于Flutter中的条件判断补充

除了在逻辑代码里用if-else和switch-case,你还可以在Widget构建时用条件判断来动态渲染UI,比如:

// 示例:如果选中了单位,显示输入框,否则提示选择单位
Widget build(BuildContext context) {
  return Column(
    children: [
      if (_value1 != null)
        TextField(...)
      else
        const Text("Please select a unit first!"),
    ],
  );
}

这样你的应用就完全实现了双向单位转换,同时也学会了Flutter里条件判断的多种用法啦!

内容的提问来源于stack exchange,提问作者Lakshan Costa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:27:43