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
相关产品推荐
相关产品推荐

