You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 11:12:19