tvOS + SwiftUI 在部分之间聚焦

cYb*_*t91 5 tvos swiftui

我已经设置了一个非常简单的 SwiftUI tvOS 应用程序。我在使用 Focus 引擎时遇到了困难。当应用程序启动时,它专注于“启动”,这是可以理解的。向下滑动,转到 StackView。在项目上向左/向右滑动效果很好。除了我无法向上滑动以进入 Launch,无论我在哪里尝试。

目标是向上滑动应该总是向上启动按钮(关注单元格会改变上面的内容)

我在这里做错了什么吗?我的印象是我没有做任何特别或复杂的事情。谢谢

在此处输入图片说明

这是我的代码:


struct ContentView: View {
    @ObservedObject private var viewModel = EnvironmentsViewModel()
    @State private var currentEnvironment: Environment?
    var environments: [Environment]?

    var body: some View {
        GeometryReader { geometry in
            VStack(spacing: 50) {
                BannerView(environment: currentEnvironment)
                    .frame(height: geometry.size.height * 0.6)
                    .clipped()

                ScrollView(.horizontal, showsIndicators: false) {
                    HStack(alignment: .center, spacing: 50) {
                        ForEach(environments ?? viewModel.environments) { environment in
                            Button(action: {
                                currentEnvironment = environment
                            }) {
                                EnvironmentCard(title: environment.title, subtitle: "Coming Soon", image: environment.image, isFocused: environment.title == currentEnvironment?.title)
                                    .frame(width: 500, height: geometry.size.height * 0.4)
                                    .edgesIgnoringSafeArea(.all)
                            }
                            .buttonStyle(PlainButtonStyle())
                        }
                    }
                }
                .padding(.leading, 50)
                .padding(.trailing, 50)
                .frame(height: geometry.size.height * 0.4)
            }
            .edgesIgnoringSafeArea([.top, .leading, .trailing])
            .onAppear {
                self.viewModel.fetch()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)
struct BannerView: View {
    var environment: Environment?

    var body: some View {
        GeometryReader { geometry in
            ZStack {
                if let environment = environment, let url = URL(string: environment.image) {
                    URLImage(url, placeholder: Image("Placeholder")) { proxy in
                        proxy.image
                            .resizable()
                            .aspectRatio(contentMode: .fill)
                    }
                    .edgesIgnoringSafeArea(.all)
                        .frame(height: geometry.size.height)
                } else {
                    Color.darkGray.edgesIgnoringSafeArea(.all)
                }

                VStack(alignment: .leading, spacing: 10) {
                    Spacer()
                    Text(environment?.title ?? "Title")
                    Text("Description")
                    Button("Launch", action: {})
                }
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.leading, 50).padding(.bottom, 50)
            }
            .frame(height: geometry.size.height)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*ybc 0

解决方案是将焦点的每一行或级别(每个可聚焦)声明为焦点部分

只需添加:.focusSection()在 HStack 视图的末尾添加一条“可聚焦”线

在这里阅读更多内容:

https://developer.apple.com/documentation/swiftui/view/focussection()

所以在你的代码中它应该看起来像这样:

struct ContentView: View {
    @ObservedObject private var viewModel = EnvironmentsViewModel()
    @State private var currentEnvironment: Environment?
    var environments: [Environment]?

    var body: some View {
        GeometryReader { geometry in
            VStack(spacing: 50) {
                BannerView(environment: currentEnvironment)
                    .frame(height: geometry.size.height * 0.6)
                    .clipped()
                    .focusSection() // <-------- ADD THIS ############

                ScrollView(.horizontal, showsIndicators: false) {
                    HStack(alignment: .center, spacing: 50) {
                        ForEach(environments ?? viewModel.environments) { environment in
                            Button(action: {
                                currentEnvironment = environment
                            }) {
                                EnvironmentCard(title: environment.title, subtitle: "Coming Soon", image: environment.image, isFocused: environment.title == currentEnvironment?.title)
                                    .frame(width: 500, height: geometry.size.height * 0.4)
                                    .edgesIgnoringSafeArea(.all)
                            }
                            .buttonStyle(PlainButtonStyle())
                        }
                    }
                }
                .padding(.leading, 50)
                .padding(.trailing, 50)
                .frame(height: geometry.size.height * 0.4)
                .focusSection() // <-------- ADD THIS ############
            }
            .edgesIgnoringSafeArea([.top, .leading, .trailing])
            .onAppear {
                self.viewModel.fetch()
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)