Reputation: 47
I am trying to achieve this view (on screenshot). The user can type in something inside this box. He should be able to make new paragraphs, but text should no longer be than the box's height, for example with linelimit. Goal:
However, when selecting TextField, the line keeps growing horizontally while typing. I tried to modify by adding ".linelimit(nil) but it doesn't work.
Another approach by me was using textEditor:
But there is also the problem with missing placeholder and modifications to layout and text padding. When I add padding, the layout looks like this:
This is my situation with TextEditor:
struct Notes: View {
@State private var notes = ""
var body: some View {
VStack (alignment: .leading, spacing: 5) {
Text("Notes")
.fontWeight(.bold)
TextEditor(text: $notes)
.submitLabel(.done)
//.padding()
.frame(height: 100, alignment: .top)
//.background(Color(.systemGray5))
.lineLimit(3)
.cornerRadius(22)
.multilineTextAlignment(.leading)
.colorMultiply(Color(.systemGray5))
}
.frame(minWidth: 0, maxWidth: .infinity)
.padding(.horizontal)
}
}
Is there an alternative I am missing?
Thanks for any advice and help. Kind regards.
Upvotes: 0
Views: 1617
Reputation: 12125
Here is a 90% solution. It deletes further text after the 3rd line break, but it cannot detect line wraps in long texts.
struct ContentView: View {
@State private var notes = ""
var body: some View {
VStack (alignment: .leading) {
Text("Notes")
.fontWeight(.bold)
CustomTextEditor("Enter your note", text: $notes)
}
.padding()
}
}
struct CustomTextEditor: View {
init(_ prompt: LocalizedStringKey, text: Binding<String>) {
self.prompt = prompt
self._text = Binding(projectedValue: text)
}
let prompt: LocalizedStringKey
@Binding var text: String
var body: some View {
ZStack(alignment: .topLeading ) {
Text(prompt)
.foregroundColor(text == "" ? .secondary : .clear)
.padding(EdgeInsets(top: 7, leading: 3, bottom: 0, trailing: 0))
TextEditor(text: $text)
// deleting everything after the 3rd linebreak
.onChange(of: text) { _ in
let stringArray = text.map { $0 }
let pos = stringArray.indices.filter { stringArray[$0] == "\n"}
if pos.count > 2 {
text = String(stringArray.prefix(upTo: pos[2]))
}
}
}
.frame(height: 82)
.padding(10)
.background(Color(.systemGray5))
.cornerRadius(20)
// getting rid of TextEditor standard background
.onAppear {
UITextView.appearance().backgroundColor = .clear
}
.onDisappear {
UITextView.appearance().backgroundColor = .systemGray5
}
}
}
Upvotes: 1