如何在SwiftUI中使用键盘箭头滚动滚动视图中的项目?



我已经建立了一个视图,具有水平类型的滚动视图与HStack的macOS应用程序。是否有一种方法来圈那些项目使用键盘箭头?

(我看到ListView有一个默认行为,但其他自定义视图类型没有)

点击这里查看截图

var body: some View {
VStack {
ScrollView(.horizontal, {
HStack {
ForEach(items.indices, id: .self) { index in
//custom view for default state and highlighted state
}
}
}
}
}

any help is appreciated :)

使用的方法

  • 在按钮上使用快捷键

替代方法
  • 使用命令(如何在macOS上检测SwiftUI键盘事件?)

代码:

struct Item: Identifiable {
var id: Int
var name: String
}
class Model: ObservableObject {
@Published var items = (0..<100).map { Item(id: $0, name: "Item ($0)")}
}

struct ContentView: View {

@StateObject private var model = Model()
@State private var selectedItemID: Int?

var body: some View {
VStack {
Button("move right") {
moveRight()
}
.keyboardShortcut(KeyEquivalent.rightArrow, modifiers: [])


ScrollView(.horizontal) {
LazyHGrid(rows: [GridItem(.fixed(180))]) {
ForEach(model.items) { item in
ItemCell(
item: item,
isSelected: item.id == selectedItemID
)
.onTapGesture {
selectedItemID = item.id
}
}
}
}
}
}

private func moveRight() {
if let selectedItemID {
if selectedItemID + 1 >= model.items.count {
self.selectedItemID = model.items.last?.id
} else {
self.selectedItemID = selectedItemID + 1
}
} else {
selectedItemID = model.items.first?.id
}
}
}
细胞

struct ItemCell: View {
let item: Item
let isSelected: Bool
var body: some View {
ZStack {
Rectangle()
.foregroundColor(isSelected ? .yellow : .blue)
Text(item.name)
}
}
}

您可以尝试这个示例代码,使用我之前的帖子方法,但使用水平滚动视图而不是列表。你必须根据你的特定应用程序调整代码。我的方法只包括几行监视关键事件的代码。

import Foundation
import SwiftUI
import AppKit
struct ContentView: View {
let fruits = ["apples", "pears", "bananas", "apricot", "oranges"]
@State var selection: Int = 0
@State var keyMonitor: Any?

var body: some View {
ScrollView(.horizontal) {
HStack(alignment: .center, spacing: 0) {
ForEach(fruits.indices, id: .self) { index in
VStack {
Image(systemName: "globe")
.resizable()
.scaledToFit()
.frame(width: 20, height: 20)
.padding(10)
Text(fruits[index]).tag(index)
}
.background(selection == index ? Color.red : Color.clear)
.padding(10)
}
}
}
.onAppear {
keyMonitor = NSEvent.addLocalMonitorForEvents(matching: [.keyDown]) { nsevent in
if nsevent.keyCode == 124 { // arrow right
selection = selection < fruits.count ? selection + 1 : 0
} else {
if nsevent.keyCode == 123 { // arrow left
selection = selection > 1 ? selection - 1 : 0
}
}
return nsevent
}
}
.onDisappear {
if keyMonitor != nil {
NSEvent.removeMonitor(keyMonitor!)
keyMonitor = nil
}
}
}
}

最新更新