如何在 iOS 使用 Flutter 显示 “Done” 按钮以关闭键盘(简洁可复用的方法)

发布: (2026年1月13日 GMT+8 17:31)
4 min read
原文: Dev.to

Source: Dev.to

在 Flutter 中构建以文本为主的界面时,最常被忽视的用户体验细节之一是用户如何关闭 iOS 键盘,尤其是在多行或数字输入框时。Android 键盘通常会提供可见的 “Done” 或 “Close” 按键,但 iOS 往往没有,导致用户只能点击输入框外部或尴尬地滚动才能收起键盘。

在 iOS 键盘上方添加自定义 “Done” 按钮的覆盖层非常简单。下面我们将探讨此功能为何重要、它如何提升文本输入的用户体验,以及如何使用 Flutter mixin 实现一个干净、可复用的解决方案。

为什么 iOS 需要自定义 “Done” 按钮?

  • 多行输入框不会显示键盘关闭按钮。
  • 数字键盘不包含回车/完成键。
  • 底部弹窗常被键盘遮挡。
  • 点击外部关闭键盘并不总是明显或可行。
  • 键盘覆盖层可能隐藏关键的 CTA 按钮。

这些问题会在内容创作页面、表单、记笔记界面或任何需要输入多于几句话的场景中产生用户体验摩擦。自定义覆盖层在键盘正上方放置一个清晰、直观的 Done 按钮,让用户能够瞬间收起键盘。

使用 Mixin 的好处

  • 无需重复样板代码。
  • 保持 widget 树整洁。
  • 可在多个页面之间复用。
  • 自动管理覆盖层的插入和移除。
  • 完全 iOS 安全(仅在 Platform.isIOS 为 true 时运行)。

应用 Mixin

下面是一个最小示例,展示如何在页面中集成该 mixin。Mixin 会自动处理焦点变化和覆盖层管理。

// Example: TextInputPage with a reusable Done‑button mixin
class TextInputPage extends StatefulWidget {
  @override
  _TextInputPageState createState() => _TextInputPageState();
}

class _TextInputPageState extends State
    with KeyboardDoneButtonMixin { // <-- your mixin
  final TextEditingController _articleController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Article Editor')),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: TextField(
          controller: _articleController,
          focusNode: focusNode, // provided by the mixin
          maxLines: null,
          decoration: const InputDecoration(
            hintText: 'Start typing...',
          ),
        ),
      ),
    );
  }
}

覆盖层行为

  • 覆盖层激活 – 当文本框获取焦点时,mixin 会插入一个 OverlayEntry,位置正好在键盘上方。
  • 动态定位MediaQuery.of(context).viewInsets.bottom 实时提供键盘高度,确保完美对齐。
  • 安全移除 – 当焦点失去或用户点击 Done 按钮时,覆盖层会被干净地移除。
  • 仅 iOS – 覆盖层在 Android、Web 或桌面平台上永不出现。

常见使用场景

  • 聊天应用。
  • 基于表单的工作流。
  • 记笔记或内容创作页面。

扩展体验

因为覆盖层本质上是普通 widget,你可以:

  • 应用自定义样式以匹配应用主题。
  • 为覆盖层的进入和退出添加动画,以获得更精致的感觉。

在键盘上方放置一个 Done 按钮这样的小细节,能够显著提升 iOS 上的文本输入体验,尤其是在内容创作或表单驱动的工作流中。Mixin 方法让代码库保持清晰、可扩展、易维护,同时提供原生感的用户体验。

Back to Blog

相关文章

阅读更多 »

SwiftUI 焦点系统 & 键盘内部

!Sebastien Lato https://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads...