swiftui - 如何在 SwiftUI 中使 UIViewRepresentable 在 tvOS 上具有焦点?
问题描述
标题说明了一切 - 我无法专注UIViewRepresentable
于 tvOS 上的 SwiftUI。任何符合View
协议的视图都可以毫无问题地聚焦,但既UIViewRepresentable
不能也UIViewControllerRepresentable
不能。
有任何想法吗?
此代码有效:
struct ContentView: View {
var body: some View {
Text("Hello, World!")
.focusable()
.onExitCommand {
print("Menu button pressed")
}
}
}
这个没有:
struct ContentView: View {
var body: some View {
ViewRepresentable()
.focusable()
.onExitCommand {
print("Menu button pressed")
}
}
}
struct ViewRepresentable: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = .red
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
谢谢!
解决方案
您需要创建一个覆盖 canBecomeFocused 的 UIView 子类以返回 true。如果您想响应焦点,您可能还想覆盖 didUpdateFocus(in:with:) 。
作为参考,我制作了一个实用程序类,让我拥有可聚焦的 UIView,并响应远程滑动和点击。
import UIKit
@available (iOS, unavailable)
@available (macCatalyst, unavailable)
class UserInputView: UIView {
weak var pressDelegate: PressableDelegate?
weak var touchDelegate: TouchableDelegate?
var touchStarted: CGFloat = 0
var lastTouch: CGFloat = 0
override init(frame: CGRect) {
super.init(frame: frame)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touchStarted = touches.first?.location(in: nil).x ?? 0
lastTouch = touchStarted
touchDelegate?.touchDown()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let thisTouch = touches.first?.location(in: nil).x ?? 0
touchDelegate?.touchMove(amount: Double((thisTouch - lastTouch)/(touches.first?.window?.frame.width ?? 1920)))
lastTouch = touches.first?.location(in: nil).x ?? 0
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touchDelegate?.touchUp()
}
override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
if isClick(presses) {
pressDelegate?.press(pressed: true)
} else {
superview?.pressesBegan(presses, with: event)
}
}
override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
if isClick(presses) {
pressDelegate?.press(pressed: false)
pressDelegate?.clicked()
} else {
superview?.pressesEnded(presses, with: event)
}
}
private func isClick(_ presses: Set<UIPress>?) -> Bool {
return presses?.map({ $0.type }).contains(.select) ?? false
}
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
pressDelegate?.focus(focused: isFocused)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var canBecomeFocused: Bool {
return true
}
}
推荐阅读
- oop - 当父类失去意义时,将兄弟类作为父类是一种好习惯吗?
- jestjs - jest 未定义 - 在 __mocks__ 文件夹中
- c# - 构造函数只能链接在初始化列表中,为什么
- php - 如何仅在 url 编码中对空间进行编码?
- typescript - 在接口中使用索引器的类型名称
- powershell - 在 Powershell 中实现 ForEach 迭代器
- css - flexbox - justify-content 属性的问题
- python - opencensus 出口商 - 一个全局或每个线程?
- python - python collections.Counter 的 C++ 等价物是什么?
- java - 无法在 Intellij 中编译 - 错误:java:从系统模块 jdk.compiler 导出包不允许使用 --release