有没有办法确定 MacOS 应用程序在后台运行后是否有任何文本输入处于活动状态?

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

特定于 MacOS,但也许与 iOS 相关的回复也可以让我走上正轨:

当应用程序失去焦点时,我需要确定应用程序范围内是否有任何文本输入(swiftUI 文本字段、NSTextField)处于活动状态。这意味着用户要么最小化我的应用程序的窗口,要么单击另一个应用程序的窗口。 我可以使用 NSApplication (或一般的 AppKit)API 来实现此目的吗? 在幕后肯定存在某些东西,因为当应用程序重新获得焦点时,应用程序上次获得焦点时处于活动状态的字段将再次处于活动状态。不幸的是,我认为无论使用什么 api 来实现这一目标都没有公开。

这是我的需求的代码示例:

struct FooView: View {
    @Environment(\.controlActiveState) private var controlActiveState

    var body: some View {
        Text("Hello World")
            .onChange(of: controlActiveState) { newState in
                guard !(newState == .inactive) else { return }
                let wasAnyTextInputActive: Bool = false // <- need to determine if any textfield was active app wide here
                guard wasAnyTextInputActive else { return }
                print("Should only be reached when the app was backgrounded with an active text input")
            }
    }
}

谢谢!

swift macos swiftui appkit
1个回答
0
投票

应用程序中接收键盘事件的

NSWindow
称为“按键窗口”,您可以在
NSApplication
keyWindow
属性
中找到它。

当应用程序未激活时,AppKit 将

keyWindow
设置为零。当应用程序再次激活时,AppKit 会恢复
keyWindow

在 AppKit(和 UIKit)中,键盘事件沿着称为“响应者链”的结构进行路由。链中的第一响应者称为“第一响应者”。您可以在 firstResponder 属性中找到窗口当前的第一响应者。

(请注意,
UIWindow 不会公开
firstResponder
属性,尽管它内部有一个属性。)
因此,当您的应用程序变得不活动时,您可以检查它是否有关键窗口,并(如果有)询问该关键窗口中的第一响应者是什么。

在键盘系统设置中,有一个“键盘导航”选项,允许非文本控件(如按钮)成为第一响应者。这允许用户完全通过键盘操纵更多的用户界面。因此,您可能还想检查第一响应者是否是

NSTextView

。请注意,在 AppKit 中,

NSTextField
通常不能成为第一响应者。当你尝试聚焦
NSTextField
时,它会偷偷地给自己一个
NSTextView
子视图,称为“字段编辑器”,字段编辑器成为第一响应者。
这个例子应该可以帮助您入门:

struct ContentView: View { @State var text = "hello" @FocusState var fieldIsFocused var body: some View { VStack { TextField("Text", text: $text) .focused($fieldIsFocused) Text(fieldIsFocused ? "Field is focused" : "Field is not focused") Button("Unfocus") { fieldIsFocused = false } } .padding() .onReceive( NotificationCenter.default .publisher(for: NSApplication.willResignActiveNotification) ) { _ in print("key window: \(NSApplication.shared.keyWindow)") print("key window's first responder: \(NSApplication.shared.keyWindow?.firstResponder)") print("key window's first responder is NSTextView: \(NSApplication.shared.keyWindow?.firstResponder is NSTextView)") } } }

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