tvOS中SwiftUI的NavigationView选中状态变化检测问题
问题分析
这个场景在tvOS SwiftUI开发中很常见:带selection参数的NavigationLink默认只会在用户按下确认键点击时更新绑定的selection值,而不会在视图获焦时自动触发更新。这就是你顶部标签始终显示“no value”的原因——焦点切换并没有同步修改selection变量。
解决方案:监听焦点状态手动更新selection
我们可以通过onFocusChange修饰符监听每个导航项的焦点变化,在视图获焦时手动把对应tag赋值给selection,让顶部标签实时同步当前获焦项。
修改后的完整代码
@State private var selection: String? = nil ZStack { Color.red.edgesIgnoringSafeArea(.all) VStack { Text(selection ?? "no value").background(Color.green) NavigationView { ScrollView(.horizontal) { HStack{ VStack { NavigationLink(destination: view2, tag: "1", selection: $selection) { Image("placeholder") .scaledToFit().frame(width:400, height: 225) } Text("Button") } // 监听焦点变化,获焦时同步selection值 .onFocusChange { isFocused in if isFocused { selection = "1" } } VStack { NavigationLink(destination: view2, tag: "2", selection: $selection) { Image("placeholder") .scaledToFit().frame(width:400, height: 225) } Text("Button") } .onFocusChange { isFocused in if isFocused { selection = "2" } } // 其他导航项重复上述逻辑即可 } }.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .bottomLeading) } } }
优化建议(多导航项场景)
如果你的导航项数量较多,重复编写onFocusChange会导致代码冗余。可以封装一个自定义View来复用逻辑:
// 自定义可聚焦导航项组件 struct FocusableNavItem: View { let tag: String let destination: some View let label: String @Binding var selection: String? var body: some View { VStack { NavigationLink(destination: destination, tag: tag, selection: $selection) { Image("placeholder") .scaledToFit().frame(width:400, height: 225) } Text(label) } .onFocusChange { isFocused in if isFocused { selection = tag } } } }
在主视图中调用这个组件:
HStack{ FocusableNavItem(tag: "1", destination: view2, label: "Button", selection: $selection) FocusableNavItem(tag: "2", destination: view2, label: "Button", selection: $selection) // 添加更多导航项... }
这样代码更整洁,后续维护也更方便。
内容的提问来源于stack exchange,提问作者Hekes Pekes
相关产品推荐
相关产品推荐

