Text Editor
는 긴 텍스트를 작성하기 위한 뷰다. 여러 줄의 텍스트를 작성하고 스크롤할 수 있다. Binding된 String 값을 전달해서 이용할 수 있다.
struct TextEditingView: View {
@State private var fullText: String = "This is some editable text..."
var body: some View {
TextEditor(text: $fullText)
}
}
TextField
는 기본적으로 placeholder 기능이 내재되어 있는 반면 TextEditor
는 그렇지 않다. 사용자가 커스텀해서 구현해야한다.
구현에서 우선적으로 padding
의 문제를 접했다. placeholder를 만들어주려면 결국 다른 뷰와 중첩을 시켜야한다. overlay, backgroud나 ZStack을 이용하는 방법이 있다. 그런데 inner padding값이 약간 걸려있는거 같은데 이때문에 입력할 때 약간 어긋난게 있다.
struct Placeholder: View {
@State private var text = ""
var body: some View {
VStack {
Divider()
TextField("", text: $text)
.overlay(alignment: .topLeading) {
Text("Placeholder")
}
Divider()
TextEditor(text: $text)
.overlay(alignment: .topLeading) {
Text("Placeholder")
}
}
}
}
TextField
TextEditor
모두 Text
를 overlay해준 결과를 살펴보자.
글씨가 약간 두꺼워지는 문제가 있지만 TextField
는 잘 겹쳐져있고 TextEditor
는 많이 어긋나있다. 바인딩된 String값이 변하면 placeholder를 없애기때문에 글씨가 두꺼워지는건 크게 문제가 되지 않는다. 그래서 placeholder로 TextEditor
를 이용했다.
placeholder로 이용할 TextEditor
를 백그라운드로 두는 방법이 제일 편했는데 상위에 있는 뷰의 컬러를 단순하게 clear로 바꾸는건 통하지 않았다.
opacity를 이용하자니 Cursor가 투명해지는게 맘에 안들었고, opacity를 0.1 이하로 하면 TextEditor
가 아예 사라지기도 했다. 빙빙 돌다가 상위 뷰의 Background를 Clear시키는게 유일한 답으로 보였고 이런 설정을 해줄 때 Introspect Library가 굉장히 유용하다.
struct Placeholder: View {
@State private var text = ""
let placeholder = "Placeholder"
var body: some View {
VStack {
Divider()
TextEditor(text: $text)
.background(alignment: .topLeading) {
TextEditor(text: .constant(text.isEmpty ? placeholder : ""))
.foregroundColor(.gray)
}
.introspectTextView { uiTextView in
uiTextView.backgroundColor = .clear
}
}
}
}
저렇게 설정을 해주니 backroundColor가 잘 적용되었다. 일반적인 modifier로는 적용되지 않는다.
SafeArea를 무시하는 문제때문에 Divider
를 추가해주었지만 placeholder는 깔끔하게 잘 동작한다.