繁体   English   中英

AppKit 上的 SwiftUI - 在弹出窗口中将焦点设置为 TextField

[英]SwiftUI on AppKit - Set Focus to a TextField in a popover

在下面的 AppKit 示例中,我希望第一个 Textfield 在弹出框出现时具有(键盘)焦点。
我怎样才能

  • 将初始焦点设置为 View 和
  • 如何控制焦点顺序
  • 如何以编程方式设置焦点,例如作为按钮操作
struct ContentView: View {
  @State var showPopup = false
  @State var text = ""
  
  var body: some View {
    VStack{
      Text("Hello, world!")
      .padding()
      Button("show Popup") { showPopup = true}
    }
    .frame(width: 300, height: 300)
    .padding()
    .popover( isPresented: $showPopup,
              arrowEdge: .trailing
    ) {
      VStack{
        Text("Popup")
        TextField("enter Text",text:$text )
      }
      .padding()
    }
  }
}

我需要在我自己的一个项目中这样做 首先,我将 NSViewController 子类化,其中视图在视图出现时成为第一响应者(聚焦)。

class FocusedTextFieldViewController: NSViewController, NSTextFieldDelegate {
    @Binding var text: String
    
    init(text: Binding<String>) {
        _text = text
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError()
    }

    var textField: NSTextField!
    
    override func loadView() {
        // Set up the text field.
        textField = NSTextField()
        
        // Set the text field's delegate
        textField.delegate = self
        
        // Set an initial text value.
        textField.stringValue = text
        
        // Set the view to the new text field.
        view = textField
    }
    
    override func viewDidAppear() {
        // Make the view the first responder.
        view.window?.makeFirstResponder(view)
    }
    
    func controlTextDidChange(_ obj: Notification) {
        // Update the text.
        text = textField.stringValue
    }
}

然后,我使用 NSViewControllerRepresentable 在 SwiftUI 中显示 NSViewController。

struct FocusedTextField: NSViewControllerRepresentable {
    @Binding var text: String
    
    func makeNSViewController(context: Context) -> some FocusedTextFieldViewController {
        return FocusedTextFieldViewController(text: $text)
    }
    
    func updateNSViewController(_ nsViewController: NSViewControllerType, context: Context) {
        let textField = nsViewController.textField
        textField?.stringValue = text
    }
}

现在,您可以使用 SwiftUI 中的“FocusedTextField”。

struct ContentView: View {
    @State private var popoverIsPresented = false
    @State private var text = ""
    var body: some View {
        Button("Show Popover") {
            // Present the popover.
            popoverIsPresented.toggle()
        }
        .popover(isPresented: $popoverIsPresented, content: {
            FocusedTextField(text: $text)
        })
    }
}

如果要取消焦点文本字段,可以将其添加到 loadView function 到 FocusedTextFieldViewController 并使用通知中心再次取消焦点文本字段。

override func loadView() {
    // Set up the text field.
    textField = NSTextField()
    
    // Set the text field's delegate
    textField.delegate = self
    
    // Set an initial text value.
    textField.stringValue = text
    
    // Set the view to the new text field.
    view = textField
    
    // Set up a notification for unfocusing the text field.
    NotificationCenter.default.addObserver(forName: Notification.Name("UnfocusTextField"), object: nil, queue: nil, using: { _ in
        // Unfocus the text field.
        self.view.window?.resignFirstResponder()
    })
}

然后,您可以在想要取消聚焦文本字段时执行此操作。

NotificationCenter.default.post(name: Notification.Name("UnfocusTextField"), object: nil)

但如果文本字段当前处于活动状态,这可能不起作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM