与全局 z-index 叠加?

Stack with global z-index?

我有一个 DataTable,其中一些单元格有 link。理想情况下,我想在将鼠标悬停在 link 上时获取有关 link 内容的预览,我可以使用 Stack 小部件实现这一点。但是,由于堆叠预览位于 DataCell 内,我似乎无法将其“z-index”提升到 table 的其余部分之上。

这对 Flutter 来说是不可能的,还是有解决办法?

我想象这种工作的唯一方法,没有更新全局 z-index 的东西,是让单元格更新全局状态,然后在上面的 Stack 上显示缩略图预览DataTable 级别。但我希望有一种不那么笨拙的方法来做到这一点...

3 个我试过但无济于事的小部件 — 它们可能有用,我不知道 —:

我的整个应用程序是 here, and the precise commit is 0303732. The relevant code is this ClickableLink 小部件:

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

import 'package:url_launcher/url_launcher.dart';

import '../schema/links.dart';

@immutable
class ClickableLink extends StatefulWidget {
  const ClickableLink({
    Key? key,
    required this.link,
    this.linkText,
    this.color = Colors.blue,
  }) : super(key: key);

  final Link link;
  final String? linkText;
  final Color color;

  @override
  State<ClickableLink> createState() => _ClickableLinkState();
}

class _ClickableLinkState extends State<ClickableLink> {
  Widget hoverWidget = const SizedBox.shrink();

  void _fetchPreview(PointerEvent pointerEvent) {
    setState(() {
      if (widget.link.host == 'online-go.com' && widget.link.prePath == 'game') {
        hoverWidget = Positioned(
          top: 25,
          child: Image.network('https://online-go.com/api/v1/games/${widget.link.id}/png'),
        );
      }
    });
  }

  void _onExit(PointerEvent pointerEvent) {
    setState(() {
      hoverWidget = const SizedBox.shrink();
    });
  }

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      onHover: _fetchPreview,
      onExit: _onExit,
      child: Stack(
        clipBehavior: Clip.none,
        children: [
          SelectableText.rich(
            TextSpan(
              text: widget.linkText ?? widget.link.id,
              style: TextStyle(color: widget.color),
              recognizer: TapGestureRecognizer()
                ..onTap = () async => launch(widget.link.completeLink),
            ),
          ),
          hoverWidget,
        ],
      ),
    );
  }
}

这里的问题是因为您的 Stack 小部件(在 ClickableLink 中定义)将处于“较低”点(在您的应用程序小部件树中)比其他所有 GameResultCell。 因此,即使更高的 z-index 仍将落后于其他 GameResultCell

要解决此问题,我建议更改您的结构并在您的结构中定义一个更高的点以显示预览。

另一种方法是使用库将预览嵌套在工具提示中。看看这个例如: just_the_tooltip: ^0.0.11+2。有了这个包,你甚至可以使用 StatelessWidget.

此处的结果与我想您所期望的更相似。

class ClickableLink extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return JustTheTooltip(
      content: Image.network(
        'https://online-go.com/api/v1/games/${widget.link.id}/png',
      ),
      child: SelectableText.rich(
        TextSpan(
          text: widget.linkText ?? widget.link.id,
          style: TextStyle(
            color: widget.color ??
                (DogempTheme.currentThemeIsLight(context)
                    ? const Color(0xff1158c7)
                    : Colors.orange.withOpacity(0.85)),
          ),
          recognizer: TapGestureRecognizer()
            ..onTap = () async => launch(widget.link.completeLink),
        ),
      ),
    );
  }
}

最后,您可以使用 Dialog,但结果会有所不同。 如果您想尝试,请查看此代码:

class _ClickableLinkState extends State<ClickableLink> {
  Widget hoverWidget = const SizedBox.shrink();

  void _fetchPreview(PointerEvent pointerEvent) {
    showDialog(
      context: context,
      builder: (context) {
        return Dialog(
          backgroundColor: Colors.transparent,
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Image.network(
                  'https://online-go.com/api/v1/games/${widget.link.id}/png'),
              const SizedBox(
                height: 16.0,
              ),
              TextButton(
                  onPressed: () async => launch(widget.link.completeLink),
                  child: const Text('Go to complete link'))
            ],
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return MouseRegion(
      onHover: _fetchPreview,
      child: Stack(
        clipBehavior: Clip.none,
        children: [
          SelectableText.rich(
            TextSpan(
              text: widget.linkText ?? widget.link.id,
              style: TextStyle(
                color: widget.color ??
                    (DogempTheme.currentThemeIsLight(context)
                        ? const Color(0xff1158c7)
                        : Colors.orange.withOpacity(0.85)),
              ),
              recognizer: TapGestureRecognizer()
                ..onTap = () async => launch(widget.link.completeLink),
            ),
          ),
        ],
      ),
    );
  }
}