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

Flutter关闭TestPage后键盘自动弹出问题求助

Flutter键盘自动弹出异常问题解决

问题描述

点击TextField时键盘正常弹出;但关闭键盘后打开TestPage()再关闭,键盘会自动弹出。即使当前不在包含TextField的第1个Tab,键盘仍会弹出,影响用户体验。

相关代码

import 'package:flutter/material.dart';
import 'test_page.dart';

class App extends StatefulWidget {
  const App({super.key});

  @override
  AppState createState() => AppState();
}

class AppState extends State<App> {
  int _currentIndex = 0;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      top: false,
      bottom: false,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('APP'),
          actions: [
            IconButton(
              icon: const Icon(Icons.settings),
              onPressed: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => const TestPage()),
                );
              },
            ),
          ],
        ),
        body: SafeArea(child: buildContent()),
        bottomNavigationBar: buildBottomNavigationBar(),
      ),
    );
  }

  Widget buildContent() {
    return IndexedStack(
      index: _currentIndex,
      children: const [
        TextField(
          autofocus: false,
        ),
        Text('d'),
        Text('g'),
      ],
    );
  }

  BottomNavigationBar buildBottomNavigationBar() {
    return BottomNavigationBar(
      currentIndex: _currentIndex,
      onTap: (index) {
        setState(
          () {
            _currentIndex = index;
          },
        );
      },
      items: const [
        BottomNavigationBarItem(
          icon: Icon(Icons.telegram_sharp),
          label: 'Page 1',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.hail),
          label: 'Page 2',
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.adb),
          label: 'Page 3',
        ),
      ],
    );
  }
}

问题复现演示

键盘自动弹出异常演示

解决方案

原因分析

IndexedStack会保留所有子组件的状态,包括TextField曾经获取过的焦点状态。当从TestPage返回原页面时,Flutter会尝试恢复之前的焦点状态,导致TextField重新获取焦点,触发键盘弹出。

解决方法1:返回页面时强制移除焦点

在打开TestPage的导航回调中,添加返回后的焦点清除逻辑:

IconButton(
  icon: const Icon(Icons.settings),
  onPressed: () {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => const TestPage()),
    ).then((_) {
      // 从TestPage返回时,移除当前所有焦点
      FocusManager.instance.primaryFocus?.unfocus();
    });
  },
),

解决方法2:切换Tab时清除焦点

如果切换到非TextField所在的Tab时,主动清除焦点,避免后续返回时触发键盘:

BottomNavigationBar buildBottomNavigationBar() {
  return BottomNavigationBar(
    currentIndex: _currentIndex,
    onTap: (index) {
      setState(() {
        _currentIndex = index;
      });
      // 切换到非第一个Tab时,移除焦点
      if (index != 0) {
        FocusManager.instance.primaryFocus?.unfocus();
      }
    },
    items: const [
      BottomNavigationBarItem(
        icon: Icon(Icons.telegram_sharp),
        label: 'Page 1',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.hail),
        label: 'Page 2',
      ),
      BottomNavigationBarItem(
        icon: Icon(Icons.adb),
        label: 'Page 3',
      ),
    ],
  );
}

解决方法3:调整状态保留逻辑(可选)

如果不需要保留所有Tab的组件状态,可以替换IndexedStack为普通的条件渲染,这样非当前Tab的组件会被销毁,不会保留焦点状态:

Widget buildContent() {
  switch (_currentIndex) {
    case 0:
      return const TextField(autofocus: false);
    case 1:
      return const Text('d');
    case 2:
      return const Text('g');
    default:
      return const SizedBox();
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 16:10:15