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

Flutter:点击输入框后如何关闭键盘的表情搜索建议?

解决方案

核心思路

iOS表情键盘的搜索建议属于系统键盘附加组件,Flutter默认API无法直接控制,需通过MethodChannel调用iOS原生代码,监听TextField聚焦事件,在再次聚焦时重置键盘输入状态,隐藏表情搜索栏。

步骤1:Flutter端实现

  • 用FocusNode监听TextField的聚焦状态
  • 通过MethodChannel向iOS原生发送重置键盘的指令
import 'package:flutter/services.dart';
import 'package:flutter/material.dart';

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

  @override
  State<EmojiTextField> createState() => _EmojiTextFieldState();
}

class _EmojiTextFieldState extends State<EmojiTextField> {
  final FocusNode _focusNode = FocusNode();
  final MethodChannel _channel = const MethodChannel('emoji_keyboard_handler');

  @override
  void initState() {
    super.initState();
    _focusNode.addListener(_onFocusChange);
  }

  void _onFocusChange() {
    if (_focusNode.hasFocus) {
      // 再次聚焦时调用原生代码重置键盘
      _channel.invokeMethod('resetEmojiKeyboard');
    }
  }

  @override
  void dispose() {
    _focusNode.removeListener(_onFocusChange);
    _focusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return TextField(
      focusNode: _focusNode,
      keyboardType: TextInputType.text,
      decoration: const InputDecoration(hintText: '输入内容'),
    );
  }
}

步骤2:iOS原生端实现

在AppDelegate.swift中添加MethodChannel处理逻辑,重置键盘输入模式并隐藏搜索建议栏:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let channel = FlutterMethodChannel(name: "emoji_keyboard_handler", binaryMessenger: controller.binaryMessenger)
    
    channel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: FlutterResult) in
      guard call.method == "resetEmojiKeyboard" else {
        result(FlutterMethodNotImplemented)
        return
      }
      self?.resetEmojiKeyboard()
      result(nil)
    }
    
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
  
  private func resetEmojiKeyboard() {
    // 获取当前活跃的TextField
    guard let textField = UIResponder.currentFirstResponder() as? UITextField else { return }
    
    // 切换为默认文本输入模式,重置键盘状态
    textField.keyboardType = .default
    textField.reloadInputViews()
    
    // iOS13+ 隐藏搜索建议栏
    if #available(iOS 13.0, *) {
      textField.inputAssistantItem.leadingBarButtonGroups = []
      textField.inputAssistantItem.trailingBarButtonGroups = []
    }
  }
}

// 扩展UIResponder获取当前第一响应者
extension UIResponder {
  static func currentFirstResponder() -> UIResponder? {
    _currentFirstResponder = nil
    UIApplication.shared.sendAction(#selector(UIResponder.findFirstResponder(_:)), to: nil, from: nil, for: nil)
    return _currentFirstResponder
  }
  
  private static weak var _currentFirstResponder: UIResponder?
  
  @objc private func findFirstResponder(_ sender: Any) {
    UIResponder._currentFirstResponder = self
  }
}

替代方案(纯Flutter,体验略逊)

若不想编写原生代码,可尝试在表情插入后,先主动失焦再重新聚焦,通过状态重置关闭搜索建议:

void _onEmojiSelected(String emoji) {
  // 插入表情到输入框
  final text = _controller.text;
  _controller.text = text + emoji;
  
  // 失焦后延迟重新聚焦,重置键盘状态
  _focusNode.unfocus();
  Future.delayed(const Duration(milliseconds: 100), () {
    _focusNode.requestFocus();
  });
}

该方案无需原生代码,但会有轻微键盘闪烁,适合快速迭代场景。


内容的提问来源于stack exchange,提问作者Burak AkşamYatmazSabahKalkmaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 17:35:04