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

SwiftUI tvOS 可聚焦HStack包裹的Button无法响应点击事件求解

问题根因

给父容器HStack添加.focusable()修饰符后,tvOS的焦点引擎会将整个HStack判定为最高优先级的可聚焦元素,直接捕获所有指向该区域的焦点事件,导致内部的CustomButton无法获得焦点,自然无法响应点击操作。

解决方案

根据你的实际需求可以选择以下两种方案:

  • 无需将按钮组作为整体聚焦,仅需要内部按钮可正常选中点击
    直接删除HStack的.focusable()修饰符即可。SwiftUI中的Button默认自带可聚焦属性,tvOS焦点引擎会自动识别HStack内部的按钮作为可聚焦元素,不需要额外给父容器添加可聚焦属性。
  • 需要将按钮组作为一个整体区域被焦点引擎识别,同时支持内部按钮单独选中
    将HStack的.focusable()替换为.focusSection()修饰符即可(该方案适用于tvOS 15+)。focusSection()的作用是将当前容器标记为一个焦点分区,焦点引擎会先将整个分区作为一个整体识别,按下遥控器确认键后即可在分区内部的子元素之间自由切换焦点,不会影响内部按钮的点击响应。

修改后的代码示例:

HStack(spacing: 40) {
    Spacer()

    CustomButton(
        title: Strings.Onboarding.Continue.title,
        action: {
            handler(selectedProducts.map(\.id))
        },
        fixedWidth: ProductView.defaultItemSize.width
    )
    .disabled(selectedProducts.count < 3)

    if selectedProducts.count < 3 {
        CustomButton(
            title: Strings.Onboarding.Skip.title,
            action: {
                handler([])
            },
            fixedWidth: ProductView.defaultItemSize.width
        )
    }

    Spacer()
}
.focusSection() // 替换原来的.focusable()

如果你需要兼容tvOS 14及更低版本,可以通过@FocusState手动管理焦点:给HStack绑定焦点状态,当HStack获得焦点时,自动将焦点切换到内部第一个可用的Button上,同时可以隐藏HStack本身的焦点样式避免视觉干扰。

原问题效果演示:
效果演示图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 17:15:02