我很难弄清楚如何在 SwiftUI 2.0 和 tvOS 14 中关注列表中的特定单元格/行。当我导航到视图时,我需要能够聚焦并选择特定记录。但是,当焦点切换到列表时,某些随机行将获得焦点。我尝试使用 ScrollView 和 List 创建一个项目列表,其中包含按钮作为项目并具有适当的prefersDefaultFocus。什么都不起作用。这是一些示例代码:
struct ChannelListView: View {
@Namespace private var namespace
@ObservedObject var viewModel : LiveViewModel
@State var selection = Set<ChannelItem>()
var body: some View {
List(viewModel.channels, selection: $selection){ item in
ScrollViewReader { proxy in
Button(action: {
}){
ChannelItemView(item: item, selectedItem: $viewModel.selectedChannel, onSelected: { id in
})
.padding(.vertical, 2)
}
.buttonStyle(ChannelButtonStyle())
.prefersDefaultFocus(item == viewModel.selectedChannel, in: namespace)
}
}
.focusScope(namespace)
}
}
找到了实现它的方法。使用
defaultFocus
修饰符就可以解决问题。您需要从列表中提供所需的元素作为其参数,另外您需要将优先级指定为 .userInitiated
,没有它,它无法正常工作。
另外,我们跟踪哪个是最后关注的(又名来自 remembersLastFocusedIndexPath
的 UIKit
)
@main
struct FocusApp: App {
var body: some Scene {
WindowGroup {
VStack(spacing: 50) {
CustomRow()
CustomRow()
}
}
}
}
struct CustomRow: View {
let items = [1, 2, 3, 4]
@FocusState private var currentFocusItem: Int?
@State private var lastFocusItem: Int?
var body: some View {
ScrollView(.horizontal) {
LazyHStack(spacing: 50) {
ForEach(items, id: \.self) { item in
Button { } label: {
Text("Item \(item)")
.frame(width: 300, height: 300, alignment: .center)
.background(Color.red)
}
.focused($currentFocusItem, equals: item)
}
}
}
.defaultFocus($currentFocusItem, lastFocusItem ?? items.first, priority: .userInitiated)
.onChange(of: currentFocusItem) {
if currentFocusItem != nil {
lastFocusItem = currentFocusItem
}
}
}
}