swiftui - 如何在 SwiftUI 中使 UIViewRepresentable 可聚焦在 tvOS 上?

标签 swiftui tvos apple-tv uiviewrepresentable

标题说明了一切 - 我无法在 tvOS 上的 SwiftUI 中关注 UIViewRepresentable。任何符合 View 协议(protocol)的 View 都可以毫无问题地聚焦,但 UIViewRepresentableUIViewControllerRepresentable 都不能。

有什么想法吗?

此代码有效:

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) {

    }
}

谢谢!

最佳答案

您需要制作一个 UIView 子类来覆盖 canBecomeFocused 以返回 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
    }
}

关于swiftui - 如何在 SwiftUI 中使 UIViewRepresentable 可聚焦在 tvOS 上?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61394186/

相关文章:

mobile-safari - 如何验证 AirPlay session

ios - Apple 应用内购买和收据刷新

admob - 是否可以集成 iAd 或 AdMob

ios - 使用airplay播放音频时如何减少截止?

ios - 为什么 EKEventStore().requestFullAccessToEvents() 适用于模拟器,但不适用于真实设备?

ios - 仪器:泄漏和分配 (tvOS)

ios - 电视操作系统 UIFocusEnvironment 没有聚焦按钮

在 iPad 上具有自定义大小的 SwiftUI sheet() 模态

ios - 有没有办法实时控制iPhone振动的强度

ios - SwiftUI 自定义 List 不能在 ForEach 中使用 Binding