Flutter:实施窥视和监控流行效果 [英] Flutter: Implementing a peek & pop effect

查看:65
本文介绍了Flutter:实施窥视和监控流行效果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图实现一个窥视&弹出效果-当用户点击并按住卡片时,将打开一个对话框,当用户不再点击屏幕上的按住键时,该对话框将消失:

I was trying to achieve a peek & pop effect - when the user taps and hold on to a card, a dialog opens, and dismissed when the user no longer tap holding on the screen:

Listener(
    onPointerDown: (PointerDownEvent e) {
      // open dialog
      showDialog(
          context: context,
          builder: (context) => Container(
                child: Card(),
              ));
    },
    onPointerUp: (PointerUpEvent e) {
      // dismiss dialog
      if (Navigator.of(context).canPop()) {
        Navigator.of(context).pop('dialog');
      }
    },
    child: Card()
)

效果很好,当我握住卡时会显示对话框,而当我不再握住水龙头时将其关闭.

It worked nicely which shows the dialog when I hold on the card and dismisses when I am no longer holding my tap.

但是我想在调用onPointerDown之前有一些延迟,例如GestureDectector中的onLongPress-我能够使对话框在长按时显示,但是当我离开屏幕时却从未调用过onTapUp:

But I wanted to have some delay before onPointerDown is called, like onLongPress from the GestureDectector - I was able to get the dialog to show up when I long pressed, but onTapUp was never invoked when I left the screen:

GestureDetector(
  onLongPress: () {
    // open dialog
    showDialog(
        context: context,
        builder: (context) => Container(child: Card()));
  },
  onTapUp: (TapUpDetails d) {
    // dismiss dialog
    if (Navigator.of(context).canPop()) {
      Navigator.of(context).pop();
    }
  },
  child: Card()
)

我尝试通过以下方式进行操作,但也从未调用过onTapUp:

I tried to do it the following way, but onTapUp was also never invoked:

  GestureDetector(
  onTapDown: (TapDownDetails d) {
    // open dialog
    showDialog(context: context, builder: (context) => Card());
  },
  onTapUp: (TapUpDetails d) {
    // dismiss dialog
    if (Navigator.of(context).canPop()) {
      Navigator.of(context).pop();
    }
  },
  child: Card())

但是下面显示出分接头已正确注册:

but the following shows that the taps were registering correctly:

GestureDetector(
  onTapDown: (TapDownDetails d) {
    print("down")
  },
  onTapUp: (TapUpDetails d) {
    print("up")
  },
  child: Card()
)

环顾四周后,我注意到了 flutter PR ,它添加了onLongPressUp-我添加了那些改变了我的抖动,然后尝试重新实现我以前的代码,如下所示:

After looking around I noticed this flutter PR which adds onLongPressUp - I added those changes to my flutter, then tried to re-implement my previous code like this:

GestureDetector(
  onLongPress: () {
    // open dialog
    showDialog(
        context: context,
        builder: (context) => Container(child: Card()));
  },
  onLongPressUp: () {
    // dismiss dialog
    if (Navigator.of(context).canPop()) {
      Navigator.of(context).pop();
    }
  },
  child: Card()
)

长按时会显示该对话框,但是当我不再长按时该对话框从未被关闭-onLongPressUp似乎没有被调用,但是以下显示它正确注册了我的拍子:

The dialog showed up on long press, but was never dismissed when I am no longer longp pressing - onLongPressUp doesn't seem to be invoked, but the following shows it is registering my taps correctly:

GestureDetector(
  onLongPress: () {
    print("longpress")
  },
  onLongPressUp: () {
    print("longpressup")
  },
  child: Card()
)

在所有这些中,仅使用侦听器,我就可以通过单击并打开来打开和关闭对话框,但是我想在调用onPointerDown之前添加一个延迟,这也尝试在onPointerDown中添加一个Timer但似乎不起作用.

Out of all these, only using Listener I was able to open and dismiss a dialog by a tap down and tap up, but I wanted to add a delay before onPointerDown is invoked, which I also tried to add a Timer in onPointerDown but doesn't seem to work.

有解决方案吗?

推荐答案

这里是一种使用带有 Stack StatefulWidget 而不是 Navigator .

Here is a solution that utilizes a StatefulWidget with a Stack instead of the Navigator.

我的代码遇到的问题是,当使用 showDialog 打开对话框时, Listener 不再接收指针事件,因此最好将所有内容保持在单个顶级小部件.

The problem I hit with your code is that the Listener no longer receives the pointer events when you open the dialog with showDialog, so it's better to keep everything under a single top-level widget.

我还使用了 Timer ,当指针升起或用户离开页面时会取消.

I'm also using a Timer that is cancelled when the pointer goes up or when the user leaves the page.

import 'dart:async';

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Timer _showDialogTimer;
  bool _dialogVisible = false;

  @override
  void dispose() {
    _showDialogTimer?.cancel();
    super.dispose();
  }

  void _onPointerDown(PointerDownEvent event) {
    _showDialogTimer = Timer(Duration(seconds: 1), _showDialog);
  }

  void _onPointerUp(PointerUpEvent event) {
    _showDialogTimer?.cancel();
    _showDialogTimer = null;
    setState(() {
      _dialogVisible = false;
    });
  }

  void _showDialog() {
    setState(() {
      _dialogVisible = true;
    });
  }

  @override
  Widget build(BuildContext context) {
    final layers = <Widget>[];

    layers.add(_buildPage());

    if(_dialogVisible) {
      layers.add(_buildDialog());
    }

    return Listener(
      onPointerDown: _onPointerDown,
      onPointerUp: _onPointerUp,
      child: Stack(
        fit: StackFit.expand,
        children: layers,
      ),
    );
  }

  Widget _buildPage() {
    return Scaffold(
      appBar: AppBar(
        title: Text('Example App'),
      ),
      body: Center(
        child: Text('Press me'),
      ),
    );
  }

  Widget _buildDialog() {
    return Container(
      color: Colors.black.withOpacity(0.5),
      padding: EdgeInsets.all(50.0),
      child: Card(),
    );
  }
}

这篇关于Flutter:实施窥视和监控流行效果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆