Reputation:
Is it possible to disable the focus ring around a TextField
in swiftUI for Mac?
Upvotes: 8
Views: 1957
Reputation: 3742
As stated in an answer by Asperi to a similar question here, it's not possible (before iOS 17 / macOS 14) to turn off the focus ring for a specific field using SwiftUI; however, the following workaround will disable the focus ring for all NSTextField
instances in the app:
extension NSTextField {
open override var focusRingType: NSFocusRingType {
get { .none }
set { }
}
}
Not ideal, but it does provide one option that doesn't require stepping too far outside of SwiftUI.
Upvotes: 5
Reputation: 3742
As identified by George Valkov in this question, as of iOS 17 / macOS 14, you can apply .focusEffectDisabled
to specific sub-views or an entire view.
TextField("Search", text: self.$searchText)
.focusEffectDisabled()
Upvotes: 2
Reputation: 71
I had that question as well, and after a couple hours of fiddling around, it seems like the answer is no. However, it is possible to wrap an NSTextField and get rid of the focus ring.
The following code has been tested in the latest release.
struct CustomTextField: NSViewRepresentable {
@Binding var text: String
init(text: Binding<String>) {
_text = text
}
func makeNSView(context: Context) -> NSTextField {
let textField = NSTextField(string: text)
textField.delegate = context.coordinator
textField.isBordered = false
textField.backgroundColor = nil
textField.focusRingType = .none
return textField
}
func updateNSView(_ nsView: NSTextField, context: Context) {
nsView.stringValue = text
}
func makeCoordinator() -> Coordinator {
Coordinator { self.text = $0 }
}
final class Coordinator: NSObject, NSTextFieldDelegate {
var setter: (String) -> Void
init(_ setter: @escaping (String) -> Void) {
self.setter = setter
}
func controlTextDidChange(_ obj: Notification) {
if let textField = obj.object as? NSTextField {
setter(textField.stringValue)
}
}
}
}
Upvotes: 7