如何在 SwiftUI 中使 UIViewRepresentable 在 tvOS 上具有焦点?
Posted
技术标签:
【中文标题】如何在 SwiftUI 中使 UIViewRepresentable 在 tvOS 上具有焦点?【英文标题】:How to make UIViewRepresentable focusable on tvOS in SwiftUI? 【发布时间】:2020-04-23 18:12:40 【问题描述】:标题说明了一切 - 我无法在 tvOS 上的 SwiftUI 中专注于 UIViewRepresentable
。任何符合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)
谢谢!
【问题讨论】:
你有什么解决办法吗?我在尝试让 UISearchController 在 SwiftUI 应用程序中工作时遇到同样的问题 @Guy***er 这个有什么更新吗?与UISearchController
有同样的问题
【参考方案1】:
您需要创建一个覆盖 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
【讨论】:
以上是关于如何在 SwiftUI 中使 UIViewRepresentable 在 tvOS 上具有焦点?的主要内容,如果未能解决你的问题,请参考以下文章