Add placeholder text to SwiftUI TextEditor
In iOS 14 we got a new SwiftUI view TextEditor that lets us display and edit multiline, scrollable text. As of iOS 14 beta 4 it doesn't have an API to define the placeholder text for it. In this article we will see how we can add one ourselves.
Check out our book!
Integrating SwiftUI into UIKit Apps
Integrating SwiftUI intoUIKit Apps
UPDATED FOR iOS 17!
A detailed guide on gradually adopting SwiftUI in UIKit projects.
- Discover various ways to add SwiftUI views to existing UIKit projects
- Use Xcode previews when designing and building UI
- Update your UIKit apps with new features such as Swift Charts and Lock Screen widgets
- Migrate larger parts of your apps to SwiftUI while reusing views and controllers built in UIKit
First we will create a TextEditor
view and give it a background color of our choice. On IOS 14 beta 4 TextEditor
has a default background that can only be unset through UITextView
appearance property.
struct ContentView: View {
@State private var text = ""
init() {
UITextView.appearance().backgroundColor = .clear
}
var body: some View {
ZStack(alignment: .topLeading) {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(Color(UIColor.secondarySystemBackground))
TextEditor(text: $text)
.padding(4)
}
.frame(width: 300, height: 400)
.font(.body)
}
}
Now we just need to check if the text in the editor is empty and insert our placeholder text view. We have to make sure that the placeholder view is inserted in the ZStack
before TextEditor
so that it's underneath TextEditor
on screen. This way it won't intercept the taps.
struct ContentView: View {
@State private var text = ""
init() {
UITextView.appearance().backgroundColor = .clear
}
var body: some View {
ZStack(alignment: .topLeading) {
RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(Color(UIColor.secondarySystemBackground))
if text.isEmpty {
Text("Placeholder Text")
.foregroundColor(Color(UIColor.placeholderText))
.padding(.horizontal, 8)
.padding(.vertical, 12)
}
TextEditor(text: $text)
.padding(4)
}
.frame(width: 300, height: 400)
.font(.body)
}
}