【问题标题】:How to display a dismissable tutorial overlay in my Flutter app?如何在我的 Flutter 应用程序中显示可关闭的教程叠加层?
【发布时间】:2021-07-30 06:16:58
【问题描述】:

我想在我的 Flutter 应用程序的屏幕上显示教程叠加层。我什至找到了一个很好的候选人,几乎可以满足我的要求:这就是https://pub.dev/packages/overlay_tutorial/ 插件。用户将按下屏幕上的帮助按钮,覆盖将弹出剪切。我不希望任何东西收到点击(https://github.com/TabooSun/overlay_tutorial/issues/26),但是如果用户点击屏幕上的任何位置,覆盖应该会消失。

我尝试使用AbsorbPointer,它成功拦截了点击,不再有点击,并且在叠加层下方发生了事情。看我的叉子:https://github.com/CsabaConsulting/overlay_tutorial/commit/9d809d51bcf55b9c8044d07d151c696bdb55abe6 但是现在也没有办法点击掉覆盖层。

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        AbsorbPointer(
          absorbing: widget.enabled && widget.absorbPointer,
          ignoringSemantics: true,
          child: _OverlayTutorialBackbone(
            overlayColor: widget.overlayColor,
            enabled: widget.enabled,
            overlayTutorialHoles: _overlayTutorialHoles,
            onEntryRectCalculated: () {
              _updateChildren();
            },
            child: widget.child,
          ),
        ),
        if (widget.enabled) ...[
          ..._overlayTutorialHoles.entries
              .map((entry) {

我需要的是 AbsorbPointer 的 onTap 或 onClick 处理程序。我可以将东西包装到 GestureDetector 中,但这会一直拦截点击和手势。这里有什么好的解决方案?

【问题讨论】:

  • 你不能把widget.child 换成AbsorbPointer,而不是_OverlayTutorialBackbone吗?喜欢_OverlayTutorialBackbone -> AbsorbPointer -> widget.child
  • 这绝对是一个解决方案的方向,但它不会单独改变任何东西。我将执行此订单交换,然后我必须弄清楚如何在_OverlayTutorialBackbone 级别捕获点击。 _OverlayTutorialBackboneSingleChildRenderObjectWidget
  • 有问题吗?通过向下移动AbsorbPointer,您现在可以将_OverlayTutorialBackbone 包裹在GestureDetector 中。 AbsorbPointer 仅防止点击到达树中它下方的小部件,因此它应该可以正常工作。
  • @PatrickMahomes 问题是,如果我将 shebang 包裹到 Gesture 检测器中,那么我可以赶走覆盖层,但 GestureDetector 仍然存在。覆盖层也始终存在,它只是智能的,并且在关闭时不会自行绘制。另一件事是我包装了 _OverlayTutorialBackbone 然后我什至不需要 AbsorbPointer(至少在水龙头方面),因为手势检测器无论如何都会吞下水龙头。也许我应该看看如何通过 GestureDetector 选择性地通过手势?
  • 我认为您不必担心这种行为。似乎 Flutter 仅使用层次结构中可用的最低 GestureDetector。我会做一个答案,让你看看。

标签: flutter onclick overlay gesture


【解决方案1】:

*这个答案来自我的评论

如果将此代码粘贴到DartPad 中,您可以看到当一个GestureDetector 在小部件树中的另一个之上时,只有较低的onTap 被执行。但是,如果较低的 GestureDetectorabsorbing: true 包裹在 AbsorbPointer 中,那么只有父 GestureDetector 才会被调用。因此,您应该能够按照我在 cmets 中的建议摆脱困境。即使这不是真的,您仍然可以有条件地将您父母 GestureDetectoronTap 设置为 null

import 'package:flutter/material.dart';

final Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  bool absorbing = false;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        GestureDetector(
          onTap: () {
            print('GestureDetector 1');
          },
          child: AbsorbPointer(
            absorbing: absorbing,
            child: GestureDetector(
              onTap: () {
                print('GestureDetector 2');
              },
              child: Container(
                height: 200.0,
                width: 200.0,
                color: Colors.red,
                alignment: Alignment.center,
                child: Text(
                  'Press me and check console',
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
              ),
            ),
          ),
        ),
        GestureDetector(
          onTap: () {
            setState(() {
              absorbing = !absorbing;
            });
          },
          child: Container(
            height: 200.0,
            width: 200.0,
            color: Colors.blue,
            alignment: Alignment.center,
            child: Text(
              'Change absorb\n(absorbing: $absorbing)',
              textAlign: TextAlign.center,
              style: TextStyle(
                color: Colors.white,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

【讨论】:

  • 到目前为止,我使用“你的父 GestureDetector 的 onTap 为 null”。
猜你喜欢
  • 2011-12-22
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-19
相关资源
最近更新 更多