SwiftUI TextField Focus onAppear highlights the whole text. How to disable highlighting on focus and just add the cursor to the end

260 views Asked by At

SwiftUI TextField Focus onAppear highlights the whole text on macOS. How to disable highlighting on focus and just add the cursor to the end.

struct ContentView: View {
    @FocusState private var textEditorFocused: Bool
    @State var textEditor: String = "Testx"
    
    var body: some View {
        VStack {
            TextField("Enter group name", text: $textEditor)
                .focused($textEditorFocused)
                .font(.system(size: 18, weight: .semibold, design: .default))
                .frame(maxWidth: .infinity, alignment: .leading)
                .textFieldStyle(.plain)
                .autocorrectionDisabled(true)
        }
        .padding()
        .onAppear {
            textEditorFocused = true
        }
    }
}

If you run this code on macOS the window launches with Textx highlighted. I just want the cursor to be appended at the end like Textx|.

Any idea how to achieve that?

I tried using TextEditor but there are other issue with that. It does not let me select text, here is my implementation of TextEditor.

struct ContentView: View {
    @FocusState private var textEditorFocused: Bool
    @State var textEditorHeight: CGFloat = 20
    @State var editMode: Bool = false
    @State var textEditor: String = "Test is always highlighted"
    
    struct ViewHeightKey: PreferenceKey {
        static var defaultValue: CGFloat { 0 }
        static func reduce(value: inout Value, nextValue: () -> Value) {
            value += nextValue()
        }
    }
    
    var body: some View {
        //  This lets me to select text
        TextEditor(text: $textEditor)
            .focused($textEditorFocused)
            .font(.system(size: 15, weight: .semibold, design: .default))
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
            .frame(height: max(20, textEditorHeight))
            .fixedSize(horizontal: false, vertical: true)
            .lineSpacing(1)
            .textFieldStyle(.plain)
        ZStack(alignment: .leading) {
            if editMode {
                //  This lets me not to select text
                TextEditor(text: $textEditor)
                    .focused($textEditorFocused)
                    .font(.system(size: 15, weight: .semibold, design: .default))
                    .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
                    .frame(height: max(20, textEditorHeight)) //  Change 20 to 80 and I can select text
                    .fixedSize(horizontal: false, vertical: true)
                    .lineSpacing(1)
                    .textFieldStyle(.plain)
            }
            Text(textEditor)
                .font(.system(size: 15, weight: .regular, design: .default))
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
                .fixedSize(horizontal: false, vertical: true)
                .opacity(editMode ? 0 : 1)
                .background(Color.white.opacity(0.001))
                .onTapGesture {
                    editMode = true
                    textEditorFocused = true
                }
                .background(GeometryReader {
                    Color.clear.preference(key: ViewHeightKey.self,
                                           value: $0.frame(in: .local).size.height)
                })
        }
        .onChange(of: editMode) { editMode in
            if !editMode {
                textEditorFocused = false
            } else {
                textEditorFocused = true
            }
        }
        
        Button("Edit Mode") {
            editMode.toggle()
        }
    }
}

0

There are 0 answers