SwiftUI TextEditor disable editing but keep tapable

Itai Aviv

I have a TextEditor that calls actionSheet when user tap on it, and displays action sheet content inside. Is it possible to keep TextEditor interactable but not editable ? I've tried .disabled() - but in this case, TextEditor becomes untapable, so user can't call ActionSheet. I would like to avoid using UIViewRepresentable to solving this.

import SwiftUI
import NavigationStack

struct CompleteSessionView: View {
    
    @StateObject var viewModel = CompleteSessionViewModel()
    @EnvironmentObject private var navigationStack: NavigationStack
    
    @Binding var isPresented: Bool
    @State var sessionManager: SessionManager
    @State var showingSkatingStyleSheet = false
    
    var body: some View {
        VStack(alignment: .leading, spacing: 5) {
            TextBox(text: $viewModel.style, placeholder: "", multiLine:false)
                .onTapGesture {
                    showingSkatingStyleSheet = true
                }
        }
        .actionSheet(isPresented: $showingSkatingStyleSheet) {
            styleActionSheet()
        }
        .onAppear {
            viewModel.style = sessionManager.skatingStyle?.localizedString ?? ""
        }
    }
    
    func styleActionSheet() -> ActionSheet {
        return ActionSheet(title: Text("new_sessions_page_style_action_sheet_title".localized), message: Text("new_sessions_page_style_action_sheet_msg".localized), buttons: [
            .default(Text(SkatingStyle.streetSkating.localizedString)) {
                sessionManager.skatingStyle = .streetSkating
                viewModel.style = SkatingStyle.streetSkating.localizedString
            },
            .default(Text(SkatingStyle.trailSkating.localizedString)) {
                sessionManager.skatingStyle = .trailSkating
                viewModel.style = SkatingStyle.trailSkating.localizedString
            },
            .default(Text(SkatingStyle.rollersDance.localizedString)) {
                sessionManager.skatingStyle = .rollersDance
                viewModel.style = SkatingStyle.rollersDance.localizedString
            },
            .default(Text(SkatingStyle.freestyle.localizedString)) {
                sessionManager.skatingStyle = .freestyle
                viewModel.style = SkatingStyle.freestyle.localizedString
            },
            .default(Text(SkatingStyle.rollerDerby.localizedString)) {
                sessionManager.skatingStyle = .rollerDerby
                viewModel.style = SkatingStyle.rollerDerby.localizedString
            },
            .default(Text(SkatingStyle.aggresive.localizedString)) {
                sessionManager.skatingStyle = .aggresive
                viewModel.style = SkatingStyle.aggresive.localizedString
            },
            .default(Text(SkatingStyle.indoorRinks.localizedString)) {
                sessionManager.skatingStyle = .indoorRinks
                viewModel.style = SkatingStyle.indoorRinks.localizedString
            },
            .default(Text(SkatingStyle.artistic.localizedString)) {
                sessionManager.skatingStyle = .artistic
                viewModel.style = SkatingStyle.artistic.localizedString
            },
            .cancel()
        ])
    }
}


struct TextBox: View {
    
    @Binding var text: String
    var placeholder: String
    var multiLine: Bool
    
    var body: some View {
        ZStack(alignment: .topLeading) {
            TextEditor(text: $text)
                .introspectTextField { textfield in
                    textfield.returnKeyType = .next
                }
                .background(Color.white)
                .overlay(
                    RoundedRectangle(cornerRadius: 5)
                        .stroke(Color.black, lineWidth: 1)
                )
                .padding(.horizontal, 8)
            
            if text.isEmpty {
                Text(placeholder)
                    .foregroundColor(.black.opacity(0.25))
                    .padding(.top, 8)
                    .padding(.horizontal, 12)
                    .allowsHitTesting(false)
            }
        }
    }
}
Simon

Is it possible to keep TextEditor interactable but not editable?

Yes. You can give a constant to the expected parameter text. You can interact with it the normal way but there is no way to edit the text. E.g.

struct ContentView: View {
    
    @State var text = "Placeholder"
    
    var body: some View {
        SecondView(text: self.$text)
    }
}

struct SecondView: View {
    
    @Binding var text: String
    
    var body: some View {
        TextEditor(text: .constant(self.text))
            .padding(50)
    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related