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

Flutter+GetX自定义TextField光标异常问题求助

问题解决:Flutter GetX TextField光标不跟随输入的问题

问题根源

你当前的写法每次在Obx刷新时都会新建一个TextEditingController,这会导致TextField丢失之前的光标状态——每次输入字符触发Obx重建后,输入框相当于被重新初始化,光标自然回到起始位置。

解决方案

核心思路是让TextEditingController成为GetX控制器的持久化成员,而不是在UI层随组件重建反复创建。

步骤1:改造GetX控制器

在你的searchCargoesController中定义并初始化两个TextEditingController,同时做好双向绑定和资源释放:

class SearchCargoesController extends GetxController {
  // 保留原有的obs变量用于业务逻辑
  final fromWhereController = ''.obs;
  final toWhereController = ''.obs;

  // 定义持久化的TextEditingController
  late final TextEditingController fromTextCtrl;
  late final TextEditingController toTextCtrl;

  @override
  void onInit() {
    super.onInit();
    // 初始化控制器并绑定初始值
    fromTextCtrl = TextEditingController(text: fromWhereController.value);
    toTextCtrl = TextEditingController(text: toWhereController.value);

    // 添加监听器,同步输入框内容到obs变量
    fromTextCtrl.addListener(() {
      fromWhereController.value = fromTextCtrl.text;
    });
    toTextCtrl.addListener(() {
      toWhereController.value = toTextCtrl.text;
    });
  }

  @override
  void onClose() {
    // 释放控制器资源,避免内存泄漏
    fromTextCtrl.dispose();
    toTextCtrl.dispose();
    super.onClose();
  }

  // 封装交换逻辑
  void swapFromTo() {
    final tempText = fromTextCtrl.text;
    fromTextCtrl.text = toTextCtrl.text;
    toTextCtrl.text = tempText;
    // 监听器会自动同步到obs变量,无需手动调用update()
  }
}

步骤2:修改UI层代码

移除UI层中每次创建TextEditingController的逻辑,直接使用控制器中定义的持久化实例,同时简化Obx或直接移除(因为TextEditingController自身会触发UI更新):

Row(
  mainAxisAlignment: MainAxisAlignment.spaceBetween,
  children: [
    SizedBox(
      height: Dimensions.height50,
      width: Dimensions.width130,
      child: CustomTextField(
        hintText: "from".tr,
        textEditingController: searchCargoesController.fromTextCtrl,
        textInputType: TextInputType.streetAddress,
        // 无需onChanged,监听器已同步内容到obs变量
      ),
    ),
    InkWell(
      onTap: () => searchCargoesController.swapFromTo(),
      child: SizedBox(
        width: Dimensions.width20,
        child: SvgPicture.asset("assets/icons/from_to1.svg"),
      ),
    ),
    SizedBox(
      height: Dimensions.height50,
      width: Dimensions.width130,
      child: CustomTextField(
        hintText: "to".tr,
        textEditingController: searchCargoesController.toTextCtrl,
        textInputType: TextInputType.streetAddress,
      ),
    ),
    Container(
      decoration: BoxDecoration(
        borderRadius: BorderRadius.circular(Dimensions.radius10),
        gradient: const LinearGradient(
          colors: [Colors.amber, Colors.yellow],
          begin: Alignment.topLeft,
          end: Alignment.bottomRight,
        ),
      ),
      child: IconButton(
        onPressed: () {},
        icon: Icon(
          Icons.search_outlined,
          color: Colors.white,
          size: Dimensions.icon20,
        ),
      ),
    ),
  ],
)

效果说明

  • 输入时光标会正常跟随输入位置,因为TextEditingController是持久化的,不会随UI重建而重置状态。
  • 点击交换图标时,两个输入框的内容会直接交换,且监听器自动同步到obs变量,确保业务逻辑中的值正确更新。
  • 无需依赖Obx也能实现UI更新(TextEditingController自身会通知TextField刷新),如果需要监听obs变量做其他业务,可以保留Obx包裹。

内容的提问来源于stack exchange,提问作者Sunnat Amirov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:27:50