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

如何在Flutter中监听iOS原生事件通知?以UIKeyboardWillShowNotification为例

Hey there! 要在Flutter里监听iOS的原生通知(比如UIKeyboardWillShowNotification这类系统通知),核心是靠MethodChannel搭建Flutter和iOS原生代码的通信桥——让原生端先监听系统通知,再把拿到的事件数据传递给Flutter侧处理。下面是完整的实现步骤,包你能搞定:

实现步骤

1. Flutter侧:配置MethodChannel并监听事件

首先在Dart代码里创建MethodChannel,然后设置回调来接收原生发来的键盘事件数据。这里以一个简单的demo为例:

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

void main() => runApp(const MyApp());

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // 定义MethodChannel的名称,要和iOS端保持一致
  static const MethodChannel _keyboardChannel = MethodChannel('com.example/keyboard_notifications');
  double _currentKeyboardHeight = 0.0;

  @override
  void initState() {
    super.initState();
    // 监听原生传递过来的方法调用
    _keyboardChannel.setMethodCallHandler((MethodCall call) async {
      switch (call.method) {
        // 处理键盘即将显示的事件
        case 'onKeyboardWillShow':
          final height = call.arguments['height'] as double;
          setState(() {
            _currentKeyboardHeight = height;
          });
          break;
        // 处理键盘即将隐藏的事件
        case 'onKeyboardWillHide':
          setState(() {
            _currentKeyboardHeight = 0.0;
          });
          break;
        default:
          throw MissingPluginException();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('iOS Keyboard Notification Demo')),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              const TextField(
                decoration: InputDecoration(hintText: "Tap here to trigger keyboard"),
              ),
              const SizedBox(height: 20),
              Text('Current Keyboard Height: ${_currentKeyboardHeight.toStringAsFixed(2)}'),
            ],
          ),
        ),
      ),
    );
  }
}

2. iOS原生侧:注册通知并传递数据到Flutter

接下来要在iOS的原生代码里(Swift或Objective-C都可以,这里用Swift举例)注册系统键盘通知,拿到键盘高度等信息后,通过MethodChannel传给Flutter。

如果你的项目用的是AppDelegate:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    // 要和Flutter侧的Channel名称完全一致
    private let channelName = "com.example/keyboard_notifications"
    private var keyboardChannel: FlutterMethodChannel!

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        guard let flutterViewController = window?.rootViewController as? FlutterViewController else {
            fatalError("Could not get FlutterViewController")
        }
        // 初始化MethodChannel
        keyboardChannel = FlutterMethodChannel(name: channelName, binaryMessenger: flutterViewController.binaryMessenger)
        
        // 注册键盘显示/隐藏的通知监听
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleKeyboardWillShow),
            name: UIResponder.keyboardWillShowNotification,
            object: nil
        )
        
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleKeyboardWillHide),
            name: UIResponder.keyboardWillHideNotification,
            object: nil
        )

        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    // 处理键盘即将显示的通知
    @objc private func handleKeyboardWillShow(_ notification: Notification) {
        guard let userInfo = notification.userInfo,
              let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
              let flutterView = window?.rootViewController?.view else {
            return
        }
        // 转换键盘frame到当前视图的坐标系,避免安全区影响高度计算
        let convertedFrame = flutterView.convert(keyboardFrame, from: nil)
        let keyboardHeight = convertedFrame.height
        
        // 把键盘高度传给Flutter
        keyboardChannel.invokeMethod("onKeyboardWillShow", arguments: ["height": keyboardHeight])
    }

    // 处理键盘即将隐藏的通知
    @objc private func handleKeyboardWillHide(_ notification: Notification) {
        keyboardChannel.invokeMethod("onKeyboardWillHide", arguments: nil)
    }

    // 销毁时移除通知监听,防止内存泄漏
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

如果你的项目用的是iOS 13+的SceneDelegate,那把通知注册的逻辑放到scene(_:willConnectTo:options:)方法里即可,其他逻辑一致。

3. 额外注意事项

  • 通知参数扩展:除了键盘高度,你还可以从notification.userInfo里拿到更多数据,比如动画时长(UIResponder.keyboardAnimationDurationUserInfoKey)、动画曲线(UIResponder.keyboardAnimationCurveUserInfoKey),按需传递给Flutter即可。
  • 内存泄漏防范:一定要在deinit(Swift)里移除通知监听,避免内存泄漏。
  • 测试环境:这个逻辑只在iOS生效,测试时请使用iOS模拟器或真机,Android端无需处理这些原生通知。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:26:38