Flutter-Web: наведение мыши -> изменить курсор на указатель

Как изменить внешний вид курсора в Flutter? Я знаю, что с помощью виджета Listener() мы можем прослушивать Mouse-Events, но я не нашел никакой информации, касающейся событий зависания для трепетной сети.

Кто-нибудь еще нашел поднос?

9 ответов

Мне было трудно найти документацию по встроенной поддержке. Вот что мне помогло: https://github.com/flutter/flutter/issues/58260

И это помогло мне, без изменения index.html и т. Д.

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

Начиная с версии сборки канала разработки 1.19.0–3.0.pre, имеется встроенная поддержка курсора-указателя. Используется тот же метод, что и ниже, с той разницей, что применяется к элементу контейнера приложения Flutter.flt-glass-pane. Использование метода ниже просто дублирует поведение.

Чтобы переопределить pointer курсор, вы можете использовать метод ниже, но применяемый к flt-glass-pane элемент.

Обходной путь для этого:

  1. Вы должны установить идентификатор (например, app-container во всем теле шаблона index.html приложения).

Вот как будет выглядеть ваш 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. Затем вам нужно создать класс-оболочку дротика. Я назвал его 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)
          ),
        )
      ],
    );
  }

}

Краткое объяснение можно найти здесь.

Более универсальное обновление, которое работает с новыми веб-проектами, созданными с помощью главного канала Flutter, можно найти здесь.

Я надеюсь, что это помогает.

Вы можете использовать InkWell, у которого есть событие onHover

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

Убедитесь, что есть что-то onTap, даже пустая функция, иначе она считается отключенной, и наведение не будет

Предыдущий метод устарел. Вот обновленный код

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

Вы по-прежнему хотите, чтобы идентификатор приложения-контейнера был прикреплен к телу вашего 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.

Самый простой способ, который я знаю

      InkWell(
        onTap: (){},
        mouseCursor: MaterialStateMouseCursor.clickable,
        ...

Из бета-версии Flutter 1.19.0-4.1.pre, добавить идентификатор в 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
    );    
}
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']);
                        },
                      )

Я считаю, что события мыши не будут работать в Интернете, виджет Listener был продемонстрирован на Google I/O 2019 и работал с мышью, но это было приложение ChromeOS, а не веб-приложение.

Согласно Flutter Web на GitHub:

В настоящее время взаимодействие с пользовательским интерфейсом рабочего стола не полностью завершено, поэтому пользовательский интерфейс, созданный с помощью flutter_web, может ощущаться как мобильное приложение, даже если он запущен в браузере рабочего стола.

Адаптированный ответ Константина Стэна

Для тех, кто хочет иметь эффект щелчка, аналогичный InkWell виджет и с опцией радиуса границы:

Добавьте в файл pubspec.yaml

dependencies:
  universal_html: ^1.1.4

Затем добавьте в файл index.html следующий тег <body id="app-container"> как показано ниже:

<!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
  );

}
Другие вопросы по тегам