在列表中,我需要知道选择了哪个项目,并且该项目必须是可单击的。
这是我尝试做的事情:
| item1 | info of the item3 (selected) |
| item2 | |
|*item3*| |
| item4 | |
我可以使用.focusable()
来实现它,但是它不可点击。
Button
或NavigationLink
可以使用,但是我无法选择当前项目。
当您使用Button
或NavigationLink
.focusable
时,请不要再打了。
所以我的问题是:
我如何选择当前项目(以便我可以显示有关此项目的更多信息)并使之可单击以显示下一个视图?
示例代码1 :可聚焦的作品,但是.onTap
在tvOS上不存在
import SwiftUI
struct TestList: Identifiable {
var id: Int
var name: String
}
let testData = [Int](0..<50).map { TestList(id: $0, name: "Row \($0)") }
struct SwiftUIView : View {
var testList: [TestList]
var body: some View {
List {
ForEach(testList) { txt in
TestRow(row: txt)
}
}
}
}
struct TestRow: View {
var row: TestList
@State private var backgroundColor = Color.clear
var body: some View {
Text(row.name)
.focusable(true) { isFocused in
self.backgroundColor = isFocused ? Color.green : Color.blue
if isFocused {
print(self.row.name)
}
}
.background(self.backgroundColor)
}
}
示例代码2 :可通过NavigationLink
单击项目,但无法获取所选项目,并且不再调用.focusable
。
import SwiftUI
struct TestList: Identifiable {
var id: Int
var name: String
}
let testData = [Int](0..<50).map { TestList(id: $0, name: "Row \($0)") }
struct SwiftUIView : View {
var testList: [TestList]
var body: some View {
NavigationView {
List {
ForEach(testList) { txt in
NavigationLink(destination: Text("Destination")) {
TestRow(row: txt)
}
}
}
}
}
}
struct TestRow: View {
var row: TestList
@State private var backgroundColor = Color.clear
var body: some View {
Text(row.name)
.focusable(true) { isFocused in
self.backgroundColor = isFocused ? Color.green : Color.blue
if isFocused {
print(self.row.name)
}
}
.background(self.backgroundColor)
}
}
答案 0 :(得分:1)
在我看来,您似乎无法在swiftui中为tvos附加click事件,这似乎是一个主要的现场活动。我提出了一个可让您将大多数swiftui组件设为可选择和可点击的hack方法。希望对您有所帮助。
首先,我需要制作一个捕获事件的UIView。
echo "A* B*" |xargs -n 1 find -name | xargs grep "whatImLookingFor" <placeholder_for_stdin> -r
可点击的委托人:
echo "A* B*" |xargs -n 1 find -name | xargs someCommand withOptions <stdin_here> andSomeOtherOptions
然后为我的视图添加swiftui扩展名
class ClickableHackView: UIView {
weak var delegate: ClickableHackDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
}
override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) {
if event?.allPresses.map({ $0.type }).contains(.select) ?? false {
delegate?.clicked()
} else {
superview?.pressesEnded(presses, with: event)
}
}
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
delegate?.focus(focused: isFocused)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var canBecomeFocused: Bool {
return true
}
}
然后,我制作一个友好的swiftui包装器,这样我就可以传入我想使其可聚焦和可单击的任何类型的组件
protocol ClickableHackDelegate: class {
func focus(focused: Bool)
func clicked()
}
用法示例:
struct ClickableHack: UIViewRepresentable {
@Binding var focused: Bool
let onClick: () -> Void
func makeUIView(context: UIViewRepresentableContext<ClickableHack>) -> UIView {
let clickableView = ClickableHackView()
clickableView.delegate = context.coordinator
return clickableView
}
func updateUIView(_ uiView: UIView, context: UIViewRepresentableContext<ClickableHack>) {
}
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
class Coordinator: NSObject, ClickableHackDelegate {
private let control: ClickableHack
init(_ control: ClickableHack) {
self.control = control
super.init()
}
func focus(focused: Bool) {
control.focused = focused
}
func clicked() {
control.onClick()
}
}
}
答案 1 :(得分:0)
不幸的是,我对tvOS上的自定义按钮样式不太满意。
但是,要在tvOS上的SwiftUI中创建可聚焦的,可选的自定义视图,可以将按钮样式设置为普通样式。这样,当您提供目标位置和自定义布局时,就可以保留系统提供的精美焦点和选择动画。只需将.buttonStyle(PlainButtonStyle())
修饰符添加到您的NavigationLink
:
struct VideoCard: View {
var body: some View {
NavigationLink(
destination: Text("Video player")
) {
VStack(alignment: .leading, spacing: .zero) {
Image(systemName: "film")
.frame(width: 356, height: 200)
.background(Color.white)
Text("Video Title")
.foregroundColor(.white)
.padding(10)
}
.background(Color.primary)
.frame(maxWidth: 400)
}
.buttonStyle(PlainButtonStyle())
}
}
Here's a screenshot of what it looks like in the simulator.
单击Siri遥控器上的按钮,或者按Enter或键盘,应该可以正常工作。