diameter/lib/components/repeat_on_hold_button.dart
2022-03-21 01:07:29 +01:00

75 lines
1.9 KiB
Dart

import 'dart:math';
import 'package:flutter/material.dart';
class RepeatOnHoldButton extends StatefulWidget {
/// Function to be called on tap and on long press.
/// Return [false] to signify that the loop should be broken after execution.
final bool? Function() onTap;
/// Specifies whether repetition speeds up when the user keeps holding the button.
final bool increaseSpeed;
/// Specifies how many ms should pass before action is repeated.
final int initialRepetitionIntervalMs;
/// Specifies by how much the interval between actions should be divided after [speedUpAfterTimes] times.
final int speedUpFactor;
/// Specifies how many times [onTap] will be called before increasing the speed.
final int speedUpAfterTimes;
final Widget child;
const RepeatOnHoldButton({
Key? key,
required this.onTap,
this.increaseSpeed = true,
this.initialRepetitionIntervalMs = 250,
this.speedUpFactor = 2,
this.speedUpAfterTimes = 5,
required this.child,
}) : super(key: key);
@override
_RepeatOnHoldButtonState createState() => _RepeatOnHoldButtonState();
}
class _RepeatOnHoldButtonState extends State<RepeatOnHoldButton> {
bool _isHeld = false;
void onLongPress() async {
setState(() {
_isHeld = true;
});
int holdCycle = 0;
int speed = widget.initialRepetitionIntervalMs;
while (true) {
final result = widget.onTap() ?? true;
if (!_isHeld || !result) {
break;
}
holdCycle++;
if (speed > 1 && holdCycle % widget.speedUpAfterTimes == 0) {
speed = max(1, (speed ~/ widget.speedUpFactor));
}
await Future.delayed(
Duration(
milliseconds: speed,
),
);
}
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onLongPress: onLongPress,
onLongPressEnd: (_) => _isHeld = false,
child: widget.child,
);
}
}