如何让 onKeyPress 在 swift 中与 TextField 配合使用?

问题描述 投票:0回答:2

实现 Markdown 文本编辑器。

每一行文字都是一个

TextField

需要切换线路🔼和🔽

第一次尝试:

TextField(...)
 .onKeyPress(.downArrow) {
    print("down")
    return .handled
 }

此事件从未被触发

第二次尝试:

import SwiftUI

class CustomTextField: NSTextField {
    override public var acceptsFirstResponder: Bool { true }
    
    override func keyDown(with event: NSEvent) {
        print("key down with character: \(String(describing: event.characters)) " )
        super.keyDown(with: event)
    }
}

struct LineEditor: NSViewRepresentable {
    @Binding var text: String
    
    init(_ text: Binding<String>) {
        self._text = text
    }
    
    typealias NSViewType = CustomTextField
    
    func makeNSView(context: Context) -> CustomTextField {
        let view = CustomTextField(string: text)
        view.delegate = context.coordinator
        return view
    }
    
    func updateNSView(_ nsView: CustomTextField, context: Context) {
        nsView.stringValue = text
    }
    
    class Coordinator: NSObject, NSTextFieldDelegate {
        var parent: LineEditor
        
        init(_ parent: LineEditor) {
            self.parent = parent
        }
        
        func controlTextDidChange(_ obj: Notification) {
            let field = obj.object as! NSTextField
            self.parent.text = field.stringValue
        }
    }
    
    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }
}

keyDown
也从未被调用过。

问题:如何在现代

SwiftUI
中正确跟踪按键事件?

swift events swiftui appkit
2个回答
1
投票

不确定这是否是最好/唯一的方法,但是为您想要处理的每个键添加一个带有绑定键盘快捷键的隐藏按钮怎么样?

例如

TextField("", text: $text)
    .background(
        ZStack {
            Button("") {
                print("focus previous field")
            }
            .keyboardShortcut(KeyboardShortcut(.upArrow, modifiers: []))

            Button("") {
                print("focus next field")
            }
            .keyboardShortcut(KeyboardShortcut(.downArrow, modifiers: []))
        }
        .opacity(0)
    )

注意:空修饰符数组 (

modifiers: []
) 很重要,因为否则快捷键还需要命令键。


1
投票

我认为您第一次尝试使用 macOS 14 Beta 中新增的 .onKeyPress 函数。该函数的文档表明,您的视图(在您第一次尝试 TextField 的情况下)必须处于焦点状态才能使该函数正常工作。 因此,为了使您的代码正常工作,您必须添加如下内容:

TextField(...)
    .focusable() // Not sure if needed
    .focused($infocus) // variable that indicates if the TextField or View is currently in focus
    .onKeyPress(keys: [.downArrow]) { arrowpress in 
        print("down")
        return .handled
    }

另请注意,我更改了函数参数并添加了

arrowpress in

其中 arrowpress in 是一个变量名称,如果您使用多个键作为参数进行检测,则存储按下的确切键。 因此,您可以使用 .onKeyPress 来检测 .downArrow 和 .upArrow,如下所示:

TextField(...)
    .focusable() // Not sure if needed
    .focused($isfocused) // variable that indicates if it is in focus
    .onKeyPress(keys: [.downArrow, .upArrow]) { arrowpress in
        if (arrowpress.characters == .downArrow) {
            // Your Code executed when Arrow down is pressed
        }
        if (arrowpress.characters == .upArrow) {
            // Your Code executed when Arrow up is pressed
        }
        return .handled
    }

请务必在需要时更改焦点,并在视图聚焦为布尔值时声明变量!

请注意,这仍处于测试阶段,功能可能会随着时间的推移而改变 注意我忘记添加 .characters 到 arrowpress

© www.soinside.com 2019 - 2024. All rights reserved.