Flutter 键盘弹跳问题修复

December 23, 2025
2 min read
By devshan

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

日期

2025-12-23

问题描述

在聊天页面中,当键盘弹出时,输入框会出现明显的”弹跳”现象:

  • 键盘升起过程中,输入框被键盘遮挡
  • 键盘动画结束后,输入框突然跳到键盘上方
  • 整个过程不平滑,使用体验很差

尝试过的方案(均失败)

1. SafeArea + resizeToAvoidBottomInset: true

SafeArea(
  child: Scaffold(
    resizeToAvoidBottomInset: true,
    ...
  ),
)

结果: 仍然弹跳

2. AnimatedPadding 手动处理

AnimatedPadding(
  duration: Duration(milliseconds: 200),
  padding: EdgeInsets.only(bottom: viewInsets.bottom),
  ...
)

结果: 仍然弹跳(因为 viewInsets.bottom 本身延迟更新)

3. 参考 DifyChat 项目结构

尝试复制其 SafeArea 包裹方式 结果: 仍然弹跳

4. 简化输入框,移除所有复杂逻辑

结果: 仍然弹跳

5. 禁用 edge-to-edge 模式

修改 styles.xml 添加 windowOptOutEdgeToEdgeEnforcement 结果: 仍然弹跳(已回滚)

6. ListView reverse: true

ListView.builder(
  reverse: true,
  ...
)

结果: 仍然弹跳

7. chat_bottom_container 包

使用原生代码获取键盘高度的第三方包 结果: 仍然弹跳

最终解决方案

参考 kelivo 项目,发现关键在于正确设置 edge-to-edge 模式

main.dart 添加系统 UI 配置

import 'package:flutter/services.dart';
 
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
 
  // 启用 edge-to-edge 模式,让内容延伸到系统栏下方
  SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
  // 设置系统栏透明
  SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    systemNavigationBarColor: Colors.transparent,
    systemNavigationBarDividerColor: Colors.transparent,
  ));
 
  // ... 其他初始化
  runApp(MyApp());
}

Scaffold 使用默认配置

Scaffold(
  resizeToAvoidBottomInset: true,  // 默认值,让 Scaffold 处理键盘避让
  body: Column(
    children: [
      Expanded(child: ListView(...)),
      InputBar(),
    ],
  ),
)

关键发现

  1. Flutter 3.38+ 的 edge-to-edge 处理

    • 新版 Flutter 需要明确设置 SystemUiMode.edgeToEdge
    • 同时需要设置系统栏透明
    • 这样 Flutter 才能正确处理键盘动画
  2. 不要同时使用多个键盘避让方案

    • 只用 Scaffold 的 resizeToAvoidBottomInset: true
    • 不要额外添加手动 padding
    • 不要使用第三方键盘处理包
  3. 参考项目

    • kelivo 项目使用 Flutter SDK ^3.8.1
    • 使用最简单的 Scaffold 默认配置
    • 关键是 main.dart 中的系统 UI 设置

相关文件

  • lib/main.dart - 添加 edge-to-edge 配置
  • lib/ui/chat_page.dart - 使用标准 Scaffold 结构

总结

问题的根本原因是 Flutter 3.x 需要明确设置 edge-to-edge 模式,否则键盘动画与布局调整不同步。解决方案非常简单,只需要在 main.dart 中添加两行系统 UI 配置即可。