问题描述
我正在尝试创建一个带有进度指示器 (CircularProgressIndicator
) 的按钮
所需的流量:
此时,我的代码在第二次按下(并按住)元素时起作用。第一次,动画控制器的 addListener 打印 2-3 次然后停止,而第二次,它成立并在用户持有元素时继续打印。不管怎样,Ontap 功能都有效。
它是在 android 和 ios 设备上本地运行时发生的
剥离的代码块:
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)),),);
}
}
输出:
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
我还简要地研究了 RawGestureDetector
但只有我的 TapGestureRecognizer
手势似乎会触发,LongPressGestureRecognizer
的手势不会......即使 TapGestureRecognizer
是已删除。
_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');
};
},);
请并感谢您的时间!
解决方法
您正在使用 Text
小部件接收
GestureDetector
,与拇指相比有一个小的命中框。这可能就是您偶尔会误点击命中框的原因。
您可以使用 debugPaintPointersEnabled
更清楚地查看行为(如果应用正在运行,则需要执行热重启):
import 'package:flutter/rendering.dart';
void main() {
// Add the config here
debugPaintPointersEnabled = true;
runApp(App());
}
您可以看到点击框不会一直闪烁,即使我们认为我们点击了文本。为了提高准确性,让我们在文本周围包裹一个大小为 Container
GestureDetector(
// ... other lines
child: Container(
width: 100,height: 50,color: Colors.blue,alignment: Alignment.center,child:
Text('Value: ${_animationController.value.toStringAsFixed(2)}')),);
你可以看到命中框现在每次都闪烁