使 TextEditor 动态高度 SwiftUI
Make TextEditor dynamic height SwiftUI
我正在尝试创建一个不断增长的 TextEditor
作为聊天视图的输入。
例如,目标是有一个扩展框,直到达到 6 行。之后它应该是可滚动的。
我已经设法用包含换行符的字符串做到这一点 \n
。
TextEditor(text: $composedMessage)
.onChange(of: self.composedMessage, perform: { value in
withAnimation(.easeInOut(duration: 0.1), {
if (value.numberOfLines() < 6) {
height = startHeight + CGFloat((value.numberOfLines() * 20))
}
if value.numberOfLines() == 0 || value.isEmpty {
height = 50
}
})
})
我创建了一个字符串扩展,其中 returns 通过调用 string.numberOfLines()
var startHeight: CGFloat = 50
换行符的数量
问题:如果我粘贴的文本包含很长的文本,当该字符串没有换行符时它不会扩展。 TextEditor 中的文本损坏了。
如何计算 TextEditor 打断的次数并在该位置放置换行符?
我找到了解决办法!
对于其他试图解决此问题的人:
我添加了一个与输入字段宽度相同的 Text
,然后使用 GeometryReader
来计算自动换行的文本高度。然后,如果您将高度除以字体大小,您将得到行数。
您可以隐藏文本字段(已在 iOS 14 和 iOS 15 beta 3 中测试)
这是根据问答改编的解决方案,
struct ChatView: View {
@State var text: String = ""
// initial height
@State var height: CGFloat = 30
var body: some View {
ZStack(alignment: .topLeading) {
Text("Placeholder")
.foregroundColor(.appLightGray)
.font(Font.custom(CustomFont.sofiaProMedium, size: 13.5))
.padding(.horizontal, 4)
.padding(.vertical, 9)
.opacity(text.isEmpty ? 1 : 0)
TextEditor(text: $text)
.foregroundColor(.appBlack)
.font(Font.custom(CustomFont.sofiaProMedium, size: 14))
.frame(height: height)
.opacity(text.isEmpty ? 0.25 : 1)
.onChange(of: self.text, perform: { value in
withAnimation(.easeInOut(duration: 0.1), {
if (value.numberOfLines() < 6) {
// new height
height = 120
}
if value.numberOfLines() == 0 || value.isEmpty {
// initial height
height = 30
}
})
})
}
.padding(4)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.appLightGray, lineWidth: 0.5)
)
}
}
还有扩展,
extension String {
func numberOfLines() -> Int {
return self.numberOfOccurrencesOf(string: "\n") + 1
}
func numberOfOccurrencesOf(string: String) -> Int {
return self.components(separatedBy:string).count - 1
}
}
我正在尝试创建一个不断增长的 TextEditor
作为聊天视图的输入。
例如,目标是有一个扩展框,直到达到 6 行。之后它应该是可滚动的。
我已经设法用包含换行符的字符串做到这一点 \n
。
TextEditor(text: $composedMessage)
.onChange(of: self.composedMessage, perform: { value in
withAnimation(.easeInOut(duration: 0.1), {
if (value.numberOfLines() < 6) {
height = startHeight + CGFloat((value.numberOfLines() * 20))
}
if value.numberOfLines() == 0 || value.isEmpty {
height = 50
}
})
})
我创建了一个字符串扩展,其中 returns 通过调用 string.numberOfLines()
var startHeight: CGFloat = 50
问题:如果我粘贴的文本包含很长的文本,当该字符串没有换行符时它不会扩展。 TextEditor 中的文本损坏了。
如何计算 TextEditor 打断的次数并在该位置放置换行符?
我找到了解决办法!
对于其他试图解决此问题的人:
我添加了一个与输入字段宽度相同的 Text
,然后使用 GeometryReader
来计算自动换行的文本高度。然后,如果您将高度除以字体大小,您将得到行数。
您可以隐藏文本字段(已在 iOS 14 和 iOS 15 beta 3 中测试)
这是根据问答改编的解决方案,
struct ChatView: View {
@State var text: String = ""
// initial height
@State var height: CGFloat = 30
var body: some View {
ZStack(alignment: .topLeading) {
Text("Placeholder")
.foregroundColor(.appLightGray)
.font(Font.custom(CustomFont.sofiaProMedium, size: 13.5))
.padding(.horizontal, 4)
.padding(.vertical, 9)
.opacity(text.isEmpty ? 1 : 0)
TextEditor(text: $text)
.foregroundColor(.appBlack)
.font(Font.custom(CustomFont.sofiaProMedium, size: 14))
.frame(height: height)
.opacity(text.isEmpty ? 0.25 : 1)
.onChange(of: self.text, perform: { value in
withAnimation(.easeInOut(duration: 0.1), {
if (value.numberOfLines() < 6) {
// new height
height = 120
}
if value.numberOfLines() == 0 || value.isEmpty {
// initial height
height = 30
}
})
})
}
.padding(4)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(Color.appLightGray, lineWidth: 0.5)
)
}
}
还有扩展,
extension String {
func numberOfLines() -> Int {
return self.numberOfOccurrencesOf(string: "\n") + 1
}
func numberOfOccurrencesOf(string: String) -> Int {
return self.components(separatedBy:string).count - 1
}
}