Mac OS SwiftUI inline text editing completions

206 Views Asked by At

Xcode on OS X has really nice inline automatic completions / suggestions while editing text with embedded documentation and such. How would I even start to achieve something like this using SwiftUI's TextEditor?

Xcode's nice inline text completions

My question here isn't about building up the data to offer for suggestions. It's about how to have TextEditor interact with my code so I can provide an inline overlay populated with suggestions?

Possibly TextEditor just doesn't do this, which would be a perfectly good answer if that's the case! If it is possible, a great answer might give a brief example of how to hook a TextEditor with in inline overlay of some kind and some pointers to relevant bits of the API to achieve this.

If this isn't possible in SwiftUI, then how to do it with UIKit would also be very interesting to know.

Thanks.

1

There are 1 best solutions below

4
workingdog support Ukraine On

you could try this (very rough) approach of using .onChange(...) for interaction, and a .popover(...) (or your own popup view) to display your suggestions.

The example code shows a popup when you type x in the TextEditor, then click on an item to select it.

struct ContentView: View {
    @State var txt = ""
    @State var showme = false
    
    @FocusState var isFocused: Bool
    
    var body: some View {
        ZStack {
            // tappable clear background to dismiss the keyboard and popup
            Color.white.opacity(0.001).ignoresSafeArea(.all)
                .onTapGesture {
                    showme = false
                    isFocused = false
                }
            
            TextEditor(text: $txt).border(.red)
                .focused($isFocused)
                .onChange(of: txt) {
                    // some logic here
                    if txt.last == "x" {
                        showme = true
                    }
                }.frame(height: 88)
            
            // in MacCatalyst/macOS
            // .popover(isPresented: $showme) {
            //    Popup(showme: $showme, txt: $txt)
            // }
            
            if showme {
                Popup(showme: $showme, txt: $txt)
            }
            
        }
    }
}

struct Popup: View {
    @Binding var showme: Bool
    @Binding var txt: String
    
    var body: some View {
        VStack {
            Button("item-1") { txt = "item-1"; showme = false}
            Button("item-2") { txt = "item-2"; showme = false}
        }
        .frame(width: 77, height: 100)
        .padding(10)
        .foregroundColor(Color.blue)
        .background(Color.yellow)
    }
}