SwiftUI:从macOS TextField删除“焦点环”突出显示边框

时间:2020-01-19 20:05:27

标签: macos focus swiftui nstextfield

我使用以下代码在SwiftUI中创建了自定义搜索栏。在iOS / Catalyst上效果很好:

SearchTextView on iOS / Catalyst

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

SearchTextView on Native macOS

使用.textFieldStyle(PlainTextFieldStyle())已从基础字段(我认为是NSTextField)中删除了大多数默认样式,但不是聚焦环。

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

public struct SearchTextView: View {

    @Binding var searchText: String

    #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)
                .textFieldStyle(PlainTextFieldStyle())
                .foregroundColor(.primary)
                .padding(8)

            Spacer()
        }
        .foregroundColor(.secondary)
        .background(backgroundColor)
        .cornerRadius(12)
        .padding()
    }

    public init(searchText: Binding<String>) {
        self._searchText = searchText
    }
}

1 个答案:

答案 0 :(得分:7)

Asperi在对类似问题here的回答中所述,目前尚无法使用SwiftUI关闭特定领域的聚焦环;但是,以下解决方法将为应用程序中的所有NSTextField实例禁用聚焦环

extension NSTextField {
    open override var focusRingType: NSFocusRingType {
        get { .none }
        set { }
    }
}

如果要在视图中用自己的自定义聚焦环替换它,则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
    }
}