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

Flutter切换普通TextField至密码TextField时焦点丢失问题求助

问题解决:Flutter密码TextField跳转时丢失焦点(HarmonyOS环境)

问题描述

Flutter环境:Channel stable 3.13.9,运行于Windows 10.0.22621.4(zh-CN);设备为HUAWEI Mate 30 Pro 5G(HarmonyOS 4.0)。页面包含普通文本输入框和密码输入框,当从普通TextField跳转至密码TextField时,密码框会丢失焦点,键盘切换为安全键盘,需再次点击才能获取焦点。尝试使用Listener绑定FocusNode的方案无效:

final _accountFocus = FocusNode();
final _passwordFocus = FocusNode();

Column(
      children: [
        Listener(
          onPointerDown: (e) => FocusScope.of(context).requestFocus(_accountFocus),
          child: TextField(
            focusNode: _accountFocus
          ),
        ),
        Listener(
          onPointerDown: (e) => FocusScope.of(context).requestFocus(_passwordFocus),
          child: TextField(
            focusNode: _passwordFocus,
            obscureText: true,
          ),
       ),
    ],
)

可行解决方案

方案1:利用onEditingComplete主动跳转焦点

在普通TextField中通过onEditingComplete直接请求密码框的焦点,同时配合textInputAction指定下一步动作:

final _accountFocus = FocusNode();
final _passwordFocus = FocusNode();

@override
void dispose() {
  _accountFocus.dispose();
  _passwordFocus.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      TextField(
        focusNode: _accountFocus,
        textInputAction: TextInputAction.next,
        onEditingComplete: () {
          FocusScope.of(context).requestFocus(_passwordFocus);
        },
        decoration: const InputDecoration(labelText: "账号"),
      ),
      TextField(
        focusNode: _passwordFocus,
        obscureText: true,
        textInputAction: TextInputAction.done,
        decoration: const InputDecoration(labelText: "密码"),
      ),
    ],
  );
}

方案2:使用FocusTraversalGroup管理焦点顺序

通过FocusTraversalGroup明确焦点遍历顺序,让系统自动处理焦点跳转:

final _accountFocus = FocusNode();
final _passwordFocus = FocusNode();

@override
void dispose() {
  _accountFocus.dispose();
  _passwordFocus.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return FocusTraversalGroup(
    policy: OrderedTraversalPolicy(),
    child: Column(
      children: [
        TextField(
          focusNode: _accountFocus,
          textInputAction: TextInputAction.next,
          decoration: const InputDecoration(labelText: "账号"),
        ),
        TextField(
          focusNode: _passwordFocus,
          obscureText: true,
          textInputAction: TextInputAction.done,
          decoration: const InputDecoration(labelText: "密码"),
        ),
      ],
    ),
  );
}

方案3:适配HarmonyOS安全键盘的延迟焦点请求

部分HarmonyOS设备的安全键盘切换会干扰焦点状态,可尝试延迟请求焦点:

final _accountFocus = FocusNode();
final _passwordFocus = FocusNode();

@override
void dispose() {
  _accountFocus.dispose();
  _passwordFocus.dispose();
  super.dispose();
}

@override
Widget build(BuildContext context) {
  return Column(
    children: [
      TextField(
        focusNode: _accountFocus,
        textInputAction: TextInputAction.next,
        onEditingComplete: () {
          // 延迟100ms请求焦点,避开安全键盘切换的干扰
          Future.delayed(const Duration(milliseconds: 100), () {
            FocusScope.of(context).requestFocus(_passwordFocus);
          });
        },
        decoration: const InputDecoration(labelText: "账号"),
      ),
      TextField(
        focusNode: _passwordFocus,
        obscureText: true,
        textInputAction: TextInputAction.done,
        decoration: const InputDecoration(labelText: "密码"),
      ),
    ],
  );
}

补充说明

该问题大概率是HarmonyOS 4.0安全键盘的切换逻辑与Flutter焦点管理的冲突导致,以上方案通过主动控制焦点或调整焦点管理逻辑来规避该问题。

内容的提问来源于stack exchange,提问作者hairui.xiang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 18:52:24