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

Flutter弹出键盘时ListView子组件被意外销毁问题如何解决?

问题原因

默认情况下Flutter的Scaffold开启了resizeToAvoidBottomInset属性,软键盘弹出时会压缩当前页面的可用高度,这个尺寸变化会通过根节点的MediaQuery通知到路由栈里的所有页面。处于下层的列表页也会因此触发重绘,而ListView.builder默认采用懒加载机制,仅会保留当前可视区域内的组件,视口高度变小后超出可视范围的列表项就会被销毁,对应你看到的dispose日志。

解决方案

方案1:列表项状态保活(推荐)

适用于需要保留列表滚动位置、列表行临时状态的场景,给列表行的State混入AutomaticKeepAliveClientMixin即可让组件滑出视口/视口变化时也不会被销毁:
修改match_chat_row.dart中的_MatchChatRowState定义:

class _MatchChatRowState extends State<MatchChatRow> with AutomaticKeepAliveClientMixin {
  // 开启保活
  @override
  bool get wantKeepAlive => true;

  @override
  void dispose(){
    print("Disposed ROW! ${widget.content}");
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context); // 必须调用父类方法
    // 原有build逻辑保持不变
    final rowHeight = 100.0;
    final rowPadding = 10.0;

    return InkWell(
      // ... 原有代码
    );
  }
}

方案2:禁止聊天页随软键盘调整大小

适用于聊天页不需要跟随软键盘上移布局的场景,直接给聊天页的Scaffold添加resizeToAvoidBottomInset: false属性即可,软键盘弹出时不会触发全局尺寸变化,下层列表自然不会重绘销毁组件:
修改chat_screen.dart中的Scaffold定义:

Scaffold(
  // 加这行禁止页面随软键盘压缩
  resizeToAvoidBottomInset: false,
  appBar: AppBar(
    title: Text("Hi")
  ),
  // 原有其他代码保持不变
)

注意:如果采用方案2,软键盘弹出时会直接覆盖当前页面内容,你需要自行处理输入框的避让逻辑,避免输入框被软键盘遮挡。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:24:04