I want to execute a method while a user is pressing down on a button. In pseudocode:
while (button.isPressed) {
executeCallback();
}
In other words, the executeCallback
method should fire repeatedly as long as the user is pressing down on the button, and stop firing when the button is released. How can I achieve this in Flutter?
Use a Listener
and a stateful widget. I also introduced a slight delay after every loop:
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'),
),
),
),
);
}
}