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

Flutter隐藏鼠标光标:Windows平台Bug的规避方案及替代方法

规避Flutter Windows平台鼠标光标不即时隐藏的问题

先看触发问题的代码:

class ExampleWidget extends StatefulWidget {
  const ExampleWidget({Key? key}) : super(key: key);

  @override
  State<ExampleWidget> createState() => _ExampleState();
}

class _ExampleState extends State<ExampleWidget> {
  bool showCursor = false;
  
  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      cursor: showCursor ? SystemMouseCursors.basic : SystemMouseCursors.none,
    );
  }
}

在Windows平台下,这段代码存在异常:当showCursor设为false时,只有用户移动鼠标,光标才会隐藏;如果设置后用户未移动鼠标,光标会持续显示,直到鼠标有移动动作才会更新状态。这是Flutter引擎的已知Bug。

下面提供几种实用的规避方案:

方案一:强制重建MouseRegion组件

给MouseRegion绑定一个和showCursor关联的Key,当showCursor状态变化时,Key同步变更,强制组件重建,从而立即触发光标状态更新:

class ExampleWidget extends StatefulWidget {
  const ExampleWidget({Key? key}) : super(key: key);

  @override
  State<ExampleWidget> createState() => _ExampleState();
}

class _ExampleState extends State<ExampleWidget> {
  bool showCursor = false;
  
  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      key: ValueKey(showCursor), // 用showCursor作为Key,状态变化时触发组件重建
      cursor: showCursor ? SystemMouseCursors.basic : SystemMouseCursors.none,
    );
  }
}

方案二:通过平台通道直接调用Windows API

绕开Flutter引擎的限制,直接调用Windows原生API控制光标显示:

Flutter端代码

import 'package:flutter/services.dart';

// 封装光标控制方法
class CursorController {
  static const MethodChannel _channel = MethodChannel('cursor_control');

  static Future<void> hideCursor() async {
    await _channel.invokeMethod('hide');
  }

  static Future<void> showCursor() async {
    await _channel.invokeMethod('show');
  }
}

Windows端代码修改

在项目Windows目录下的runner.cpp中添加平台通道实现:

#include <windows.h>
#include "flutter_window.h"
#include "flutter/generated_plugin_registrant.h"

// 注册光标控制通道
void RegisterCursorChannel(FlutterWindow* window) {
  auto channel = std::make_unique<flutter::MethodChannel<flutter::EncodableValue>>(
      window->flutter_engine()->messenger(), "cursor_control",
      &flutter::StandardMethodCodec::GetInstance());

  channel->SetMethodCallHandler(
      [](const flutter::MethodCall<flutter::EncodableValue>& call,
         std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
        if (call.method_name() == "hide") {
          ShowCursor(FALSE);
          result->Success();
        } else if (call.method_name() == "show") {
          ShowCursor(TRUE);
          result->Success();
        } else {
          result->NotImplemented();
        }
      });
}

int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
                      _In_ wchar_t* command_line, _In_ int show_command) {
  // ... 保留原有代码 ...
  FlutterWindow window(project);
  RegisterCursorChannel(&window); // 注册光标控制通道
  // ... 保留原有代码 ...
}

在Widget中使用

class _ExampleState extends State<ExampleWidget> {
  bool showCursor = false;

  @override
  void didUpdateWidget(covariant ExampleWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    // 光标状态变化时调用原生方法
    if (showCursor != oldWidget.showCursor) {
      showCursor ? CursorController.showCursor() : CursorController.hideCursor();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(); // 无需再依赖MouseRegion
  }
}

方案三:使用第三方封装包

可以选择维护活跃的跨平台光标控制第三方包,直接调用封装好的方法来隐藏/显示光标,省去自己编写原生代码的麻烦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:45:39