首页 > 解决方案 > Editable Text() [ Text() that can be TextField() on double tap]

问题描述

Some time ago I had a problem with making UI logic of view that can be Label and EditBox both:

I mean Text() -> doubleClick action -> display TextEdit() -> fill it with new text -> Enter key press -> text changes saved and displayed in Text()

solution is in answer below

标签: swiftui

解决方案


import SwiftUI

@available(macOS 10.15, *)
public struct EditableLabel: View {
    @Binding var text: String
    @State private var newValue: String = ""
    
    @State var editProcessGoing = false { didSet{ newValue = text } }
    
    let onEditEnd: () -> Void
    
    public init(_ txt: Binding<String>, onEditEnd: @escaping () -> Void) {
        _text = txt
        self.onEditEnd = onEditEnd
    }
    
    @ViewBuilder
    public var body: some View {
        ZStack {
            // Text variation of View
            Text(text)
                .opacity(editProcessGoing ? 0 : 1)
            
            // TextField for edit mode of View
            TextField("", text: $newValue, 
                          onEditingChanged: { _ in }, 
                          onCommit: { text = newValue; editProcessGoing = false; onEditEnd() } )
                .opacity(editProcessGoing ? 1 : 0)
        }
        // Enable EditMode on double tap
        .onTapGesture(count: 2, perform: { editProcessGoing = true } )
        // Exit from EditMode on Esc key press
        .onExitCommand(perform: { editProcessGoing = false; newValue = text })
    }
}

sample of usage:

EditableLabel($name, onEditEnd: { print("New name is *\(name)* ") } )

推荐阅读