Unlike TextField, TextEditor does not natively provide a placeholder feature. We’ll explore how to add a placeholder to TextEditor using ZStack.
Problem
TextField allows for simple placeholder configuration:
TextField("placeholder text", text: $input)
Additionally, TextEditor does not provide a default border, requiring developers to manually add .overlay or .border modifiers to visually distinguish the input area. These missing basic elements create inconvenience for developers using TextEditor.
Solution: Placeholder Implementation Using ZStack
To solve this problem, we can use ZStack to display a placeholder text over the TextEditor and hide it when the user enters text.
ZStack(alignment: .leading) {
if note.isEmpty {
VStack {
Text("write something...")
.padding(.top, 15)
.padding(.leading, 20)
.foregroundColor(.gray)
Spacer(minLength: 60)
}.zIndex(1)
}
VStack {
TextEditor(text: $note)
.frame(minHeight: 150)
.padding(.horizontal, 20)
.padding(.vertical, 5)
Spacer()
}.zIndex(0)
}
Code Analysis
Let’s examine this implementation step by step:
-
Using ZStack: ZStack is a container that stacks views along the z-axis. This allows placing the TextEditor and placeholder text on top of each other.
-
Conditional Rendering: The if note.isEmpty condition displays the placeholder only when the input field is empty.
-
zIndex Setting: Setting the placeholder text’s zIndex to 1 and TextEditor’s zIndex to 0 ensures the placeholder appears above the TextEditor.
-
Alignment and Padding: Setting ZStack’s alignment to .leading and applying appropriate padding ensures the placeholder text appears in the correct position within the TextEditor.
-
Styling: Using foregroundColor(.gray) displays the placeholder text in gray, distinguishing it from the actual input text.
Conclusion
Adding a placeholder to TextEditor is a common task in SwiftUI that is not natively supported. By utilizing ZStack and conditional rendering, this issue can be resolved.
A lingering question is why Apple still hasn’t provided a basic placeholder feature for TextEditor. Given that TextField already has this functionality, extending the same API to TextEditor seems logical.