I'm trying to create a button with a progress indicator (CircularProgressIndicator
)
Desired flow:
- The user taps on the button it should fire a function
- The user presses the button (and holds), it should trigger the animation and fire a function
- When the user releases their hold, it should reset the animation and fire a function
At this point, my code works on the second time pressing (and holding) the element. The first time around, the animation controller's addListener prints 2-3 times and then stops, whereas the second time, it holds true and continues to print as the user holds the element. Ontap functionality works regardless.
It's happening while running locally on an android and an ios device
Stripped code block:
import 'package:flutter/material.dart';
import 'package:homi_frontend/constants/woopen_colors.dart';
class ProgressButton extends StatefulWidget {
ProgressButton({
@required this.onTap,
@required this.onLongPress,
@required this.onLongPressUp,
this.duration = const Duration(seconds: 60),
});
final Function onTap;
final Function onLongPress;
final Function onLongPressUp;
final Duration duration;
@override
ProgressButtonState createState() => ProgressButtonState();
}
class ProgressButtonState extends State<ProgressButton>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
bool _beingPressed = false;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: widget.duration,
);
_animationController.addListener(_animationListener);
_animationController.addStatusListener(_animationStatusListener);
super.initState();
}
void _animationListener() {
print('Animation Controller Listener');
setState(() {});
}
void _animationStatusListener(AnimationStatus status) {
print('_animationStatusListener');
if (status == AnimationStatus.completed) {
print(
'Completed duration of ${widget.duration}, fire _handleOnLongPressUp');
_handleOnLongPressUp();
}
if (status == AnimationStatus.forward) {
this.setState(() {
_beingPressed = true;
});
}
}
void _handleOnLongPress() {
print('_handleOnLongPress');
try {
_animationController.forward();
} catch (e) {
print('_handleOnLongPress error: ${e.toString()}');
} finally {
if (_animationController.status == AnimationStatus.forward) {
print('Controller has been started, fire widget.onLongPress');
widget.onLongPress();
}
}
}
void _handleOnLongPressUp() {
print('_handleOnLongPressUp');
try {
this.setState(() {
_beingPressed = false;
});
_animationController.reset();
} catch (e) {
print('_handleOnLongPressUp error: ${e.toString()}');
} finally {
if (_animationController.status == AnimationStatus.dismissed) {
print('Controller has been dismissed, fire widget.onLongPressUp');
widget.onLongPressUp();
}
}
}
@override
dispose() {
_animationController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
key: Key('progressButtonGestureDetector'),
behavior: HitTestBehavior.opaque,
onLongPress: _handleOnLongPress,
onLongPressUp: _handleOnLongPressUp,
onTap: widget.onTap,
child: Container(
width: 80,
height: 80,
child: Text(_animationController.value.toStringAsFixed(2)),
),
);
}
}
Output:
flutter: _handleOnLongPress
flutter: _animationStatusListener
flutter: Controller has been started, fire widget.onLongPress
(2) flutter: Animation Controller Listener
# here it just seems to loose its connection, but if I press (and hold) again, I get:
flutter: _handleOnLongPress
flutter: _animationStatusListener
flutter: Controller has been started, fire widget.onLongPress
(326) flutter: Animation Controller Listener
flutter: _handleOnLongPressUp
flutter: Animation Controller Listener
flutter: _animationStatusListener
flutter: Controller has been dismissed, fire widget.onLongPressUp
I've also looked briefly into RawGestureDetector
but only my TapGestureRecognizer
gestures seem to fire, the LongPressGestureRecognizer
ones don't... even if TapGestureRecognizer
s are removed.
_customGestures = Map<Type, GestureRecognizerFactory>();
_customGestures[TapGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
() => TapGestureRecognizer(debugOwner: this),
(TapGestureRecognizer instance) {
instance
..onTapDown = (TapDownDetails details) {
print('onTapDown');
}
..onTapUp = (TapUpDetails details) {
print('onTapUp');
}
..onTap = () {
print('onTap');
}
..onTapCancel = () {
print('onTapCancel');
};
},
);
_customGestures[LongPressGestureRecognizer] =
GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
() => LongPressGestureRecognizer(
duration: widget.duration, debugOwner: this),
(LongPressGestureRecognizer instance) {
instance
..onLongPress = () {
print('onLongPress');
}
..onLongPressStart = (LongPressStartDetails details) {
print('onLongPressStart');
_animationController.forward();
}
..onLongPressMoveUpdate = (LongPressMoveUpdateDetails details) {
print('onLongPressMoveUpdate');
}
..onLongPressEnd = (LongPressEndDetails details) {
print('onLongPressEnd');
_animationController.reset();
}
..onLongPressUp = () {
print('onLongPressUp');
};
},
);
Please & thank you for your time!