Как создать многострочное TextField в SwiftUI?
Я пытался создать многострочное TextField в SwiftUI, но я не могу понять, как.
Вот код, который у меня сейчас есть:
struct EditorTextView : View {
@Binding var text: String
var body: some View {
TextField($text)
.lineLimit(4)
.multilineTextAlignment(.leading)
.frame(minWidth: 100, maxWidth: 200, minHeight: 100, maxHeight: .infinity, alignment: .topLeading)
}
}
#if DEBUG
let sampleText = """
Very long line 1
Very long line 2
Very long line 3
Very long line 4
"""
struct EditorTextView_Previews : PreviewProvider {
static var previews: some View {
EditorTextView(text: .constant(sampleText))
.previewLayout(.fixed(width: 200, height: 200))
}
}
#endif
Но это вывод:
![enter image description here]()
Ответы
Ответ 1
Обновление: хотя Xcode11 beta 4 теперь поддерживает TextView
, я обнаружил, что перенос UITextView
по-прежнему является лучшим способом заставить работать редактируемый многострочный текст. Например, TextView
имеет проблемы с отображением, когда текст не отображается должным образом внутри представления.
Оригинальный (бета 1) ответ:
На данный момент вы можете обернуть UITextView
для создания компонуемого View
:
import SwiftUI
import Combine
final class UserData: BindableObject {
let didChange = PassthroughSubject<UserData, Never>()
var text = "" {
didSet {
didChange.send(self)
}
}
init(text: String) {
self.text = text
}
}
struct MultilineTextView: UIViewRepresentable {
@Binding var text: String
func makeUIView(context: Context) -> UITextView {
let view = UITextView()
view.isScrollEnabled = true
view.isEditable = true
view.isUserInteractionEnabled = true
return view
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
}
struct ContentView : View {
@State private var selection = 0
@EnvironmentObject var userData: UserData
var body: some View {
TabbedView(selection: $selection){
MultilineTextView(text: $userData.text)
.tabItemLabel(Image("first"))
.tag(0)
Text("Second View")
.font(.title)
.tabItemLabel(Image("second"))
.tag(1)
}
}
}
#if DEBUG
struct ContentView_Previews : PreviewProvider {
static var previews: some View {
ContentView()
.environmentObject(UserData(
text: """
Some longer text here
that spans a few lines
and runs on.
"""
))
}
}
#endif
![enter image description here]()
Ответ 2
С помощью Text()
вы можете добиться этого, используя .lineLimit(nil)
, и документация предполагает, что это должно работать и для TextField()
. Тем не менее, я могу подтвердить, что в настоящее время это работает не так, как ожидалось.
Я подозреваю ошибку - рекомендую заполнить отчет с помощью Feedback Assistant. Я сделал это, и идентификатор FB6124711.
Ответ 3
Я только что попытался создать многострочное текстовое поле с помощью swiftui в GM-версии Xcode версии 11.0 (11A419c), используя lineLimit(). Это все еще не работает. Я не могу поверить, что Apple еще не исправила это. Многострочное текстовое поле довольно часто встречается в мобильных приложениях.
Ответ 4
Это оборачивает UITextView в бета 6 Xcode версии 11.0 (все еще работает на Xcode 11 GM seed 2):
import SwiftUI
struct ContentView: View {
@State var text = ""
var body: some View {
VStack {
Text("text is: \(text)")
TextView(
text: $text
)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
}
}
}
struct TextView: UIViewRepresentable {
@Binding var text: String
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UITextView {
let myTextView = UITextView()
myTextView.delegate = context.coordinator
myTextView.font = UIFont(name: "HelveticaNeue", size: 15)
myTextView.isScrollEnabled = true
myTextView.isEditable = true
myTextView.isUserInteractionEnabled = true
myTextView.backgroundColor = UIColor(white: 0.0, alpha: 0.05)
return myTextView
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.text = text
}
class Coordinator : NSObject, UITextViewDelegate {
var parent: TextView
init(_ uiTextView: TextView) {
self.parent = uiTextView
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
return true
}
func textViewDidChange(_ textView: UITextView) {
print("text now: \(String(describing: textView.text!))")
self.parent.text = textView.text
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Ответ 5
Привет @gabriellanata, если вы хотите показывать только многострочный текст, используйте UILabel
и вы хотите добавлять или редактировать текст после запуска приложения, вы можете использовать UITextView
.