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

macOS下SwiftUI嵌套在Button中的TextField无法监听焦点变化

macOS SwiftUI List行内TextField焦点监听+整行点击激活解决方案

针对你遇到的两个问题,给你一套适配macOS的可行方案:

核心问题原因

  • 用Button包裹TextField:macOS下Button作为可交互控件,会拦截TextField的焦点事件,导致焦点通知失效(iOS因为Button的交互逻辑不同所以正常)。
  • 直接加onTapGesture:未设置contentShape时,只有Row内有内容的区域响应点击;同时手势会覆盖TextField空白区域的原生点击响应,导致只有点文本才能激活。

解决方案代码

用FocusState管理焦点,给Row设置可点击区域,同时保留TextField的原生交互:

import SwiftUI

struct ListItem: Identifiable {
    let id = UUID()
    var content: String
}

struct TextFieldListDemo: View {
    @State private var listItems = [ListItem(content: "第一行"), ListItem(content: "第二行")]
    // 用ListItem的id标记当前聚焦的TextField
    @FocusState private var focusedItemID: UUID?

    var body: some View {
        List($listItems) { $item in
            HStack {
                TextField("输入内容", text: $item.content)
                    .focused($focusedItemID, equals: item.id)
                    // 监听当前TextField的焦点变化
                    .onFocusChanged { isFocused in
                        if isFocused {
                            print("TextField \(item.id) 获得焦点")
                        } else {
                            print("TextField \(item.id) 失去焦点")
                        }
                    }
                Spacer() // 让TextField占满行宽,空白区域属于Row
            }
            .contentShape(Rectangle()) // 让整个Row区域都能响应点击
            .onTapGesture {
                // 点击整行时激活对应的TextField
                focusedItemID = item.id
            }
        }
    }
}

方案说明

  1. FocusState管理焦点:替代原来的通知方式,这是SwiftUI原生的焦点管理API,在macOS上更稳定。
  2. contentShape扩展点击区域:让整个Row的矩形区域都能响应点击手势,解决只有文本区域可点的问题。
  3. 手势仅触发焦点切换:点击Row时只是设置focusedItemID,不会拦截TextField本身的点击事件,空白区域点击也能正常激活输入框。

这样既实现了整行点击激活TextField,又能正常监听焦点的获取/失去状态,完美适配macOS。

内容的提问来源于stack exchange,提问作者Z S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 00:02:14