flutter中InkWell 和 GestureDetector快速、频繁点击时表现出不响应或“点不到”的情况分析
背景:
之前没有详细的用到这一块,最近自己做了一个竞速类的工具,主打一个快速输入之后快速提交。
结果,老是提交之后,不能快速的拿到输入栏的结果,明明已经输入了,却显示null。
一开始以为是放在setState方法中,有延迟,于是拿了出来,不在setState方法中改变初始值。
后面发现还是不行,输入快,点击快的情况下,还是会把输入的内容漏掉。
这时的我不得不分析我是否用错了控件。
原来代码如下:
class CustomButton extends StatelessWidget {
final String label;
final VoidCallback onTap;
final VoidCallback? onLongPress; // 添加这个字段
static const TextStyle top_two_style = TextStyle(
fontSize: 18, color: Color(0xff353e4d), fontWeight: FontWeight.w500);
const CustomButton({Key? key, required this.label, required this.onTap,this.onLongPress}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(1),
child: Material(
color: AppColors.APPKeyLightColor,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(2)),
),
child: InkWell(
onTap: onTap,
onLongPress: onLongPress, // 可以为空
splashColor: AppColors.APPKeyDarkMoreColor, // 按下时的颜色
borderRadius: BorderRadius.all(Radius.circular(2)),
child: Container(
padding: const EdgeInsets.all(9),
alignment: Alignment.center,
child: Text(
label,
style: top_two_style,
),
),
),
),
);
}
}
我怀疑是InkWell的问题,因为看源码可以知道,他有个水波纹,有一个固定的延迟,用于显示水波纹动画效果。这种延迟在快速点击时会影响响应速度。
之前使用他是因为他自带背景色,方便简单,没想到,这个成了问题所在:
于是改了代码:
class CustomButton extends StatefulWidget {
final String label;
final VoidCallback onTap;
final VoidCallback? onLongPress;
const CustomButton({
Key? key,
required this.label,
required this.onTap,
this.onLongPress,
}) : super(key: key);
@override
_CustomButtonState createState() => _CustomButtonState();
}
class _CustomButtonState extends State<CustomButton> {
bool _isPressed = false;
static const TextStyle top_two_style = TextStyle(
fontSize: 18,
color: Color(0xff353e4d),
fontWeight: FontWeight.w500,
);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(1),
child: GestureDetector(
onTap: widget.onTap,
onLongPress: widget.onLongPress,
onTapDown: (_) {
setState(() {
_isPressed = true;
});
},
onTapUp: (_) {
setState(() {
_isPressed = false;
});
},
onTapCancel: () {
setState(() {
_isPressed = false;
});
},
child: Container(
decoration: BoxDecoration(
color: _isPressed
? AppColors.APPKeyDarkMoreColor // 仅短按时改变背景色
: AppColors.APPKeyLightColor, // 默认颜色
borderRadius: BorderRadius.circular(2),
),
padding: const EdgeInsets.all(9),
alignment: Alignment.center,
child: Text(
widget.label,
style: top_two_style,
),
),
),
);
}
}
GestureDetector能实现更复杂的效果,这里也只好换成这个了。就是代码量加了不少。
于是就完美解决。
注意这个坑,有的需要水波纹,有的不需要水波纹,谨慎处理。
当然排查的时候还有这几个点:
- 手势冲突:
在快速点击时,可能会有多个手势事件发生,导致手势识别器无法正确解析。例如,当手指快速滑过按钮时,可能会被识别为拖动手势而不是点击。- 布局重绘:
如果在点击时有其他逻辑触发了 UI 重绘(比如状态变化导致重新构建),可能会影响手势识别。- 异步操作阻塞:
如果点击事件触发了耗时的异步操作(例如网络请求或繁重的计算),并且没有在单独的异步任务中处理,UI线程可能会被阻塞,导致点击事件无法立即响应。
这几个都可能造成响应慢的情况,逐一分析即可。