Flutter Execute Method 长按按钮
Posted
技术标签:
【中文标题】Flutter Execute Method 长按按钮【英文标题】:Flutter Execute Method so long the button pressed 【发布时间】:2019-02-07 06:15:25 【问题描述】:我想在用户按下按钮时执行一个方法。在伪代码中:
while (button.isPressed)
executeCallback();
换句话说,只要用户按下按钮,executeCallback
方法就会重复触发,并在按钮释放时停止触发。如何在 Flutter 中实现这一点?
【问题讨论】:
那么GestureLongPressCallback onLongPress
属性有什么问题?
压机操作后onLongPress被触发但压机操作过程中需要的问题
这没什么意义:如果您只是进行正常的快速按下(意味着您在短时间内松开手指),那么您如何获得长按?
正是我需要的,我需要的方法将被执行很长时间,以至于手指放在按钮上
这个想法是关于音乐播放器中的前言按钮,当用户点击按钮时我需要寻找歌曲前言
【参考方案1】:
使用Listener
和有状态小部件。我还在每个循环之后引入了一点延迟:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(brightness: Brightness.dark),
home: MyHomePage(),
);
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage>
int _counter = 0;
bool _buttonPressed = false;
bool _loopActive = false;
void _increaseCounterWhilePressed() async
// make sure that only one loop is active
if (_loopActive) return;
_loopActive = true;
while (_buttonPressed)
// do your thing
setState(()
_counter++;
);
// wait a bit
await Future.delayed(Duration(milliseconds: 200));
_loopActive = false;
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(),
body: Center(
child: Listener(
onPointerDown: (details)
_buttonPressed = true;
_increaseCounterWhilePressed();
,
onPointerUp: (details)
_buttonPressed = false;
,
child: Container(
decoration: BoxDecoration(color: Colors.orange, border: Border.all()),
padding: EdgeInsets.all(16.0),
child: Text('Value: $_counter'),
),
),
),
);
【讨论】:
这正是我所需要的 请同时处理onPointerCancel
;)【参考方案2】:
没有监听器的更简单的方法如下:
GestureDetector(
child: InkWell(
child: Icon(Icons.skip_previous_rounded),
onTap: widget.onPrevious,
),
onLongPressStart: (_) async
isPressed = true;
do
print('long pressing'); // for testing
await Future.delayed(Duration(seconds: 1));
while (isPressed);
,
onLongPressEnd: (_) => setState(() => isPressed = false),
);
【讨论】:
【参考方案3】:基于ThinkDigital 的解决方案,我的观察是InkWell
包含执行此操作所需的所有事件,而无需额外的GestureDetector
(我发现GestureDetector
会干扰长按时的墨水动画) .这是我为一个宠物项目实现的控件,该控件在按住时触发其事件并减少延迟(这是一个带有图标的圆形按钮,但任何使用 InkWell
的东西都可以):
/// A round button with an icon that can be tapped or held
/// Tapping the button once simply calls [onUpdate], holding
/// the button will repeatedly call [onUpdate] with a
/// decreasing time interval.
class TapOrHoldButton extends StatefulWidget
/// Update callback
final VoidCallback onUpdate;
/// Minimum delay between update events when holding the button
final int minDelay;
/// Initial delay between change events when holding the button
final int initialDelay;
/// Number of steps to go from [initialDelay] to [minDelay]
final int delaySteps;
/// Icon on the button
final IconData icon;
const TapOrHoldButton(
Key? key,
required this.onUpdate,
this.minDelay = 80,
this.initialDelay = 300,
this.delaySteps = 5,
required this.icon)
: assert(minDelay <= initialDelay,
"The minimum delay cannot be larger than the initial delay"),
super(key: key);
@override
_TapOrHoldButtonState createState() => _TapOrHoldButtonState();
class _TapOrHoldButtonState extends State<TapOrHoldButton>
/// True if the button is currently being held
bool _holding = false;
@override
Widget build(BuildContext context)
var shape = CircleBorder();
return Material(
color: Theme.of(context).dividerColor,
shape: shape,
child: InkWell(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(
widget.icon,
color:
Theme.of(context).textTheme.headline1?.color ?? Colors.white70,
size: 36,
),
),
onTap: () => _stopHolding(),
onTapDown: (_) => _startHolding(),
onTapCancel: () => _stopHolding(),
customBorder: shape,
),
);
void _startHolding() async
// Make sure this isn't called more than once for
// whatever reason.
if (_holding) return;
_holding = true;
// Calculate the delay decrease per step
final step =
(widget.initialDelay - widget.minDelay).toDouble() / widget.delaySteps;
var delay = widget.initialDelay.toDouble();
while (_holding)
widget.onUpdate();
await Future.delayed(Duration(milliseconds: delay.round()));
if (delay > widget.minDelay) delay -= step;
void _stopHolding()
_holding = false;
它在行动:
【讨论】:
很好的回答,非常感谢!以上是关于Flutter Execute Method 长按按钮的主要内容,如果未能解决你的问题,请参考以下文章
flutter textfield 长按输入框出现剪切/复制/粘贴的菜单如何设置中文?
页面报错误:HTTP Status 500 - Method "execute" failed for object com.oa.action.loginAction@3c346
行中图像的动态列表,带有换行符(之间没有空格),允许长按图像打开编辑选项 - Flutter
Flutter开发iOS上TextField长按或反复点击报错No CupertinoLocalizations found.
android的报错提示:java.lang.IllegalStateException: Could not execute method for android:onClick