Flutter中TextFormField用onTapOutside时滚动不丢焦点的解决方案
解决Flutter中TextFormField滚动时触发onTapOutside失焦的问题
方案一:通过滚动通知判断滚动状态
利用NotificationListener监听滚动的开始与结束,标记当前是否处于滚动状态,在onTapOutside中仅当未滚动时执行失焦操作:
bool _isScrolling = false; @override Widget build(BuildContext context) { return Scaffold( body: NotificationListener<ScrollNotification>( onNotification: (notification) { if (notification is ScrollStartNotification) { _isScrolling = true; } else if (notification is ScrollEndNotification) { _isScrolling = false; } return false; }, child: SingleChildScrollView( child: Column( children: [ TextFormField( onTapOutside: (event) { if (!_isScrolling) { FocusScope.of(context).focusedChild?.unfocus(); } }, ), ...List.generate(100, (_) => const Text('Test')), ], ), ), ), ); }
方案二:过滤onTapOutside的事件类型
通过判断PointerDownEvent的属性,过滤掉滚动相关触发事件,只响应真正的点击操作:
TextFormField( onTapOutside: (event) { // 仅响应鼠标左键点击或触摸点击,排除触摸板滚动等事件 if (event.buttons == kPrimaryButton && event.pointerDeviceKind != PointerDeviceKind.trackpad) { FocusScope.of(context).focusedChild?.unfocus(); } }, )
修正TextFieldTapRegion的用法
你之前的TextFieldTapRegion未生效,需将其包裹在滚动组件外部,同时结合滚动状态判断:
bool _isScrolling = false; @override Widget build(BuildContext context) { return Scaffold( body: NotificationListener<ScrollNotification>( onNotification: (notification) { if (notification is ScrollStartNotification) { _isScrolling = true; } else if (notification is ScrollEndNotification) { _isScrolling = false; } return false; }, child: TextFieldTapRegion( onTapOutside: (_) { if (!_isScrolling) { FocusManager.instance.primaryFocus?.unfocus(); } }, child: SingleChildScrollView( child: Column( children: [ TextFormField(), ...List.generate(100, (_) => const Text('Test')), ], ), ), ), ), ); }
内容的提问来源于stack exchange,提问作者Heropolis Da2ny
相关产品推荐
相关产品推荐

