SwiftUI TextEditor with placeholder


Greetings, traveler!

It may come as a surprise, but Apple has yet to provide a built-in solution for creating a placeholder in SwiftUI TextEditor. However, creating a custom view for this purpose is not difficult. Let’s explore some of the many ways we can solve this problem.

First, we need to create a custom View and give it a name. Inside the view, we’ll create two properties: one for the text and the other for the placeholder.

import SwiftUI

public struct TextEditorWithPlaceholder: View {
    
    @State private var text = ""
    private let placeholder: String
    
    public init(
        text: String = "",
        placeholder: String
    ) {
        
        self.text = text
        self.placeholder = placeholder
    }
    
    public var body: some View {
        EmtyView()
    }
}

Next, we’ll place the TextEditor inside the View itself, and we’ll create an overlay for the placeholder using simple text. We’ll align the overlay so that it looks like a native placeholder and add the desired color. Finally, we’ll use the allowsHitTesting modifier to prevent user taps from interacting with the Text View.

import SwiftUI

public struct TextEditorWithPlaceholder: View {
    
    @State private var text = ""
    private let placeholder: String
    
    public init(
        text: String = "",
        placeholder: String
    ) {
        
        self.text = text
        self.placeholder = placeholder
    }
    
    public var body: some View {
        TextEditor(text: $text)
            .overlay(alignment: .topLeading) {
                Text(placeholder)
                    .foregroundColor(Color(uiColor: .placeholderText))
                    .multilineTextAlignment(.leading)
                    .opacity(text.isEmpty ? 1 : 0)
                    .padding(.vertical, 8)
                    .padding(.horizontal, 4)
                    .allowsHitTesting(false)
            }
    }
}

This small tutorial will help you solve an urgent problem quickly and quite universally. The source code is on GitHub. See you soon!