Flutter:实施窥视和监控流行效果 [英] Flutter: Implementing a peek & pop effect
问题描述
我正试图实现一个窥视&弹出效果-当用户点击并按住卡片时,将打开一个对话框,当用户不再点击屏幕上的按住键时,该对话框将消失:
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屋!