【问题标题】:Flutter-Web:鼠标悬停->将光标更改为指针
【发布时间】:2019-10-06 06:53:32
【问题描述】:

更新(2021/05/11):

Flutter 现在原生实现了悬停事件小部件。

对于像 RaisedButton 这样的小部件和像 hoverColor 或 hoverElevation 这样的属性有一个 MouseCursor。

https://api.flutter.dev/flutter/rendering/MouseCursor-class.html

您也可以在接受的答案中说明的其他任何地方使用 InkWell。


原问题:

如何在 Flutter 中更改光标外观? 我知道使用Listener() 小部件我们可以监听鼠标事件, 但我还没有找到任何关于颤动网络悬停事件的信息。 有人找到解决方案了吗?

【问题讨论】:

    标签: flutter flutter-web


    【解决方案1】:

    我很难找到有关现在内置支持的文档。这对我有帮助:https://github.com/flutter/flutter/issues/58260

    这对我有用,无需更改 index.html 等。

    MouseRegion(
      cursor: SystemMouseCursors.click,
        child: GestureDetector(
          child: Icon(
            Icons.add_comment,
            size: 20,
            ),
          onTap: () {},
        ),
      ),
    

    另见官方文档:https://api.flutter.dev/flutter/rendering/MouseCursor-class.html

    Widget build(BuildContext context) {
      return Center(
        child: MouseRegion(
          cursor: SystemMouseCursors.text,
          child: Container(
            width: 200,
            height: 100,
            decoration: BoxDecoration(
              color: Colors.blue,
              border: Border.all(color: Colors.yellow),
            ),
          ),
        ),
      );
    }
    

    这里https://api.flutter.dev/flutter/material/MaterialStateMouseCursor-class.html 是官方文档中的另一个精彩示例,“......定义了一个鼠标光标,当其小部件被禁用时解析为 SystemMouseCursors.forbidden。”

    【讨论】:

    • Flutter 的变化很快。几周前Khari Lane's answer 工作但我无法做到现在。这很好用,不需要一堆自定义代码或更改 index.html。
    • 在 2021 年,这似乎是通过对按钮的 1.22 更新自动完成的
    • 这个导入也需要import 'package:flutter/rendering.dart';
    【解决方案2】:

    dev 通道构建版本 1.19.0–3.0.pre 开始,内置了对指针光标的支持。使用与以下相同的方法,不同之处在于应用于 Flutter 应用程序容器元素 flt-glass-pane。使用波纹管方法只会复制行为。

    为了覆盖pointer 光标,您可以使用下面的方法,但应用于flt-glass-pane 元素。

    解决方法如下:

    1. 您必须在应用的index.htmlbody上设置一个id(例如app-container /strong> 模板)。

    这就是您的 index.html 的样子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>My awesome app</title>
    </head>
    <body id="app-container">
      <script src="main.dart.js" type="application/javascript"></script>
    </body>
    </html>
    
    1. 接下来,您必须创建一个包装 dart 类。我称之为 hand_cursor.dart
    import 'package:flutter_web/gestures.dart';
    import 'package:flutter_web/widgets.dart';
    import 'package:universal_html/html.dart' as html;
    // see https://pub.dev/packages/universal_html
    
    class HandCursor extends MouseRegion {
    
      // get a reference to the body element that we previously altered 
      static final appContainer = html.window.document.getElementById('app-container');
    
      HandCursor({Widget child}) : super(
        onHover: (PointerHoverEvent evt) {
          appContainer.style.cursor='pointer';
          // you can use any of these: 
          // 'help', 'wait', 'move', 'crosshair', 'text' or 'pointer'
          // more options/details here: http://www.javascripter.net/faq/stylesc.htm
        },
        onExit: (PointerExitEvent evt) {
          // set cursor's style 'default' to return it to the original state
          appContainer.style.cursor='default';
        },
        child: child
      );
    
    }
    
    1. 之后,无论您想在何处显示手形光标,都必须将元素包装在此 HandCursor 包装器中。请参阅下面的 awesome_button.dart 类:
    import 'package:awesome_app/widgets/containers/hand_cursor.dart';
    import 'package:flutter_web/material.dart';
    import 'package:flutter_web/widgets.dart';
    
    class AwesomeButton extends StatelessWidget {
    
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: <Widget>[
            HandCursor(
              child: IconButton(
                onPressed: () {
                  // do some magic
                },
                icon: Icon(Icons.star)
              ),
            )
          ],
        );
      }
    
    }
    

    可以在here找到一个简短的解释。

    一个更通用的更新,适用于使用 Flutter ma​​ster 频道创建的新 Web 项目,可以找到 here

    我希望它有所帮助。

    【讨论】:

    • 感谢您的回答,这似乎是合法的。有时间我会试试的,我会回来的。
    【解决方案3】:

    您可以使用具有 onHover 事件的 InkWell

    InkWell(
        onTap: () {},
        onHover: (value) {
          setState(() {
            isHovered = value;
          });
        },
        child: Container(
          width: 50,
          height: 72,
          color: Colors.black   
        )
    );
    

    确保有onTap,即使是一个空的功能,否则它被认为是禁用的,悬停将不起作用

    【讨论】:

      【解决方案4】:

      以前的方法已弃用。这是更新的代码

      import 'package:flutter/gestures.dart';
      import 'package:flutter/widgets.dart';
      import 'package:universal_html/prefer_sdk/html.dart' as html;
      
      class HandCursor extends MouseRegion {
        static final appContainer = html.window.document.getElementById('app-container');
        HandCursor({Widget child})
            : super(
                onHover: (PointerHoverEvent evt) {
                  appContainer.style.cursor = 'pointer';
                },
                onExit: (PointerExitEvent evt) {
                  appContainer.style.cursor = 'default';
                },
                child: child,
              );
      }
      

      然后在您的 pubspec.yaml 文件中,将 Universal_html 作为包添加为依赖项。版本可能会改变。

      dependencies:
        flutter:
          sdk: flutter
        universal_html: ^1.1.4
      

      您仍然希望将 app-container 的 ID 附加到您的 html 正文。这是我的 html 文件。

      <!DOCTYPE html>
      <html>
      <head>
        <meta charset="UTF-8">
        <title>Your App Title</title>
      </head>
      <body id="app-container">
        <script src="main.dart.js" type="application/javascript"></script>
      </body>
      </html>
      
      

      您希望将 HandCursor 小部件的代码放在它自己的文件中。你可以称它为 hand_cursor.dart。要将其用于您想要显示手的小部件,请将其导入您正在处理的文件中并将所需的小部件包装在 HandCursor 小部件中。

      【讨论】:

        【解决方案5】:

        从 Flutter beta 版 1.19.0-4.1.pre 开始,将 id 添加到 body 并设置光标不起作用。因为flt-glass-pane 正在替换光标。 所以解决办法就是直接设置光标到flt-glass-pane

        以下是正在运行的更新。

        class HandCursor extends MouseRegion {
            static final appContainer = html.window.document.querySelectorAll('flt-glass-pane')[0];
            HandCursor({Widget child}) : super(
                onHover: (PointerHoverEvent evt) {
                    appContainer.style.cursor='pointer';
                },
                onExit: (PointerExitEvent evt) {
                    appContainer.style.cursor='default';
                },
                child: child
            );    
        }
        

        【讨论】:

        • 找这个很久了,谢谢!!
        【解决方案6】:

        我认为鼠标事件在网络上不起作用,Listener Widget 在 Google I/O 2019 上进行了演示并与鼠标一起使用,但那是作为 ChromeOS 应用程序而不是网络应用程序。

        根据Flutter web on GitHub

        此时,桌面 UI 交互尚未完全完成,因此使用 flutter_web 构建的 UI 可能感觉就像是移动应用,即使在桌面浏览器上运行也是如此。

        【讨论】:

        • 谢谢,我确实在想我错过了什么,因为他们在 I/O 上有一些工作
        【解决方案7】:
        final appContainer 
             = html.document.getElementsByTagName('body')[0] as html.Element;
        
                    GestureDetector(
                                child: MouseRegion(
                                  child: Text(
                                    'https://github.com/yumi0629',
                                    style: textStyle,
                                  ),
                                  onHover: (_) => appContainer.style.cursor = 'pointer',
                                  onExit: (_) => appContainer.style.cursor = 'default',
                                ),
                                onTap: () {
                                  print('open');
                                  js.context.callMethod(
                                      'open', ['https://github.com/yumi0629']);
                                },
                              )
        

        【讨论】:

          【解决方案8】:

          Constantin Stan 改编的答案

          对于那些想要具有类似于InkWell 小部件的点击效果并带有边框半径选项的人:

          添加到您的 pubspec.yaml 文件中

          dependencies:
            universal_html: ^1.1.4
          

          然后在 index.html 文件中添加如下标签 &lt;body id="app-container"&gt; 如下:

          <!DOCTYPE html>
          <html>
          <head>
            <meta charset="UTF-8">
            <title>Your App Title</title>
          </head>
          <body id="app-container">
            <script src="main.dart.js" type="application/javascript"></script>
          </body>
          </html>
          

          最后创建以下小部件并使用封装的所有必要小部件:

          import 'package:flutter/foundation.dart';
          import 'package:flutter/gestures.dart';
          import 'package:flutter/material.dart';
          import 'package:universal_html/prefer_sdk/html.dart' as html;
          
          class InkWellMouseRegion extends InkWell {
            InkWellMouseRegion({
              Key key,
              @required Widget child,
              @required GestureTapCallback onTap,
              double borderRadius = 0,
            }) : super(
                    key: key,
                    child: !kIsWeb ? child : HoverAware(child: child),
                    onTap: onTap,
                    borderRadius: BorderRadius.circular(borderRadius),
                  );
          }
          
          class HoverAware extends MouseRegion {
          
            // get a reference to the body element that we previously altered 
            static final appContainer = html.window.document.getElementById('app-container');
          
            HoverAware({Widget child}) : super(
              onHover: (PointerHoverEvent evt) {
                appContainer.style.cursor='pointer';
                // you can use any of these: 
                // 'help', 'wait', 'move', 'crosshair', 'text' or 'pointer'
                // more options/details here: http://www.javascripter.net/faq/stylesc.htm
              },
              onExit: (PointerExitEvent evt) {
                // set cursor's style 'default' to return it to the original state
                appContainer.style.cursor='default';
              },
              child: child
            );
          
          }
          

          【讨论】:

          • 如果你的应用是网页版的,你不需要依赖 "universal_html" 包,只要 'import 'dart:html' as html' 就可以了。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-10
          • 1970-01-01
          • 1970-01-01
          • 2022-01-26
          • 1970-01-01
          • 2012-12-15
          相关资源
          最近更新 更多