点击CupertinoSegmentedControl时TextField的onFocusChange未触发问题求助
问题解决:点击CupertinoSegmentedControl时TextField的onFocusChange未触发
问题原因
CupertinoSegmentedControl默认不参与焦点系统,点击它不会主动请求焦点,导致TextField的焦点不会被夺走,因此onFocusChange事件不会触发。
两种可行解决方案
方案1:让CupertinoSegmentedControl可请求焦点
给CupertinoSegmentedControl包裹Focus组件,使其能够获取焦点,点击时自动触发TextField的失焦事件:
Column( // task type children: [ Focus( child: TextField( controller: titleController, decoration: createDecoration("Title of task", widget.state.validationData.titleHelper), ), onFocusChange: (hasFocus) { print("TASK TITLE has focus: $hasFocus"); if (!hasFocus) { taskEditBloc.add(TaskEditDataEntered(taskData: widget.state.taskData!.copyWith(title: () => titleController.text))); } }, ), // 用Focus包裹SegmentedControl,允许它请求焦点 Focus( canRequestFocus: true, child: CupertinoSegmentedControl( children: { 0: const Text('A'), 1: const Text('B'), }, groupValue: taskType, onValueChanged: (value) { taskEditBloc.add(TaskEditDataEntered(taskData: widget.state.taskData!.copyWith(taskType: () => value))); }, ), ), ], )
方案2:手动触发TextField失焦
在CupertinoSegmentedControl的onValueChanged回调里,主动让TextField失去焦点:
Column( // task type children: [ Focus( child: TextField( controller: titleController, decoration: createDecoration("Title of task", widget.state.validationData.titleHelper), ), onFocusChange: (hasFocus) { print("TASK TITLE has focus: $hasFocus"); if (!hasFocus) { taskEditBloc.add(TaskEditDataEntered(taskData: widget.state.taskData!.copyWith(title: () => titleController.text))); } }, ), CupertinoSegmentedControl( children: { 0: const Text('A'), 1: const Text('B'), }, groupValue: taskType, onValueChanged: (value) { // 主动让TextField失焦 titleController.unfocus(); // 或者使用FocusScope全局失焦:FocusScope.of(context).unfocus(); taskEditBloc.add(TaskEditDataEntered(taskData: widget.state.taskData!.copyWith(taskType: () => value))); }, ), ], )
补充说明
- 方案1更符合Flutter焦点系统的设计逻辑,自动处理焦点转移;
- 方案2更直接,适合需要精准控制焦点的场景;
- 原代码中的定时器可以移除,因为现在
onFocusChange会先触发,不需要延迟等待。
内容的提问来源于stack exchange,提问作者w461
相关产品推荐
相关产品推荐

