SwiftUI:从 macOS TextField 中删除“焦点环”高亮边框

The*_*eil 11 macos focus nstextfield swiftui

我使用以下代码在 SwiftUI 中创建了一个自定义搜索栏。它在 iOS / Catalyst 上运行良好:

iOS / Catalyst 上的 SearchTextView

...但是当在 macOS 上本地运行时,“聚焦环”突出显示的边框样式(当用户选择文本字段时)反而会破坏效果:

原生 macOS 上的 SearchTextView

Using.textFieldStyle(PlainTextFieldStyle())已经从底层字段(我认为是NSTextField)中删除了大部分默认样式,但不是聚焦环。

有没有办法删除这个?我尝试创建一个自定义TextFieldStyle并应用它,但找不到任何修饰符来设置该边框的样式。

public struct SearchTextView: View {
    
    @Binding var searchText: String

    #if !os(macOS)
    private let backgroundColor = Color(UIColor.secondarySystemBackground)
    #else
    private let backgroundColor = Color(NSColor.controlBackgroundColor)
    #endif
    
    public var body: some View {
        
        HStack {
            
            Spacer()
            
            #if !os(macOS)
            Image(systemName: "magnifyingglass")
            #else
            Image("icons.general.magnifyingGlass")
            #endif
            
            TextField("Search", text: self.$searchText)
                .textFieldStyle(PlainTextFieldStyle())
                .foregroundColor(.primary)
                .padding(8)
        
            Spacer()
        }
        .foregroundColor(.secondary)
        .background(backgroundColor)
        .cornerRadius(12)
        .padding()
    }
    
    public init(searchText: Binding<String>) {
        self._searchText = searchText
    }
}
Run Code Online (Sandbox Code Playgroud)

The*_*eil 10

正如Asperi这里对类似问题的回答中所述,(还)不可能使用 SwiftUI 关闭特定字段的对焦环;但是,以下解决方法将禁用NSTextField应用程序中所有实例的聚焦环

extension NSTextField {
    open override var focusRingType: NSFocusRingType {
        get { .none }
        set { }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您想在视图中将其替换为您自己的自定义对焦环,该onEditingChanged参数可以帮助您实现这一点(请参见下面的示例);然而,不幸的是,当用户键入第一个字母时,它会在 macOS 上调用,而不是当他们第一次单击该字段时(这并不理想)。

理论上,您可以改用修饰符中的onFocusChange闭包focusable,但目前这些 macOS 文本字段似乎不会调用它(从 macOS 10.15.3 开始)。

public struct SearchTextView: View {

    @Binding var searchText: String

    @State private var hasFocus = false

    #if !os(macOS)
    private var backgroundColor = Color(UIColor.secondarySystemBackground)
    #else
    private var backgroundColor = Color(NSColor.controlBackgroundColor)
    #endif

    public var body: some View {

        HStack {

            Spacer()

            #if !os(macOS)
            Image(systemName: "magnifyingglass")
            #else
            Image("icons.general.magnifyingGlass")
            #endif

            TextField("Search", text: self.$searchText, onEditingChanged: { currentlyEditing in
                self.hasFocus = currentlyEditing // If the editing state has changed to be currently edited, update the view's state
            })
                .textFieldStyle(PlainTextFieldStyle())
                .foregroundColor(.primary)
                .padding(8)

            Spacer()
        }
        .foregroundColor(.secondary)
        .background(backgroundColor)
        .cornerRadius(12)
        .border(self.hasFocus ? Color.accentColor : Color.clear, width: self.hasFocus ? 3 : 0)
        .padding()
    }

    public init(searchText: Binding<String>) {
        self._searchText = searchText
    }
}
Run Code Online (Sandbox Code Playgroud)


Geo*_*kov 3

从 iOS 17 / macOS 14 开始,您可以使用.focusEffectDisabled. 您还可以将其应用于按钮或整个视图。

TextField("Search", text: self.$searchText)
.focusEffectDisabled()
Run Code Online (Sandbox Code Playgroud)