tvOS + SwiftUI 各部分之间的聚焦

问题描述 投票:0回答:1

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

目标是向上滑动应始终到达“启动”按钮(关注单元格会更改上面的内容)

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

这是我的代码:


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()
            }
        }
    }
}
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)
        }
    }
}
swiftui tvos
1个回答
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()
            }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.