How to Create a Multi-Line Text Inside a Scrollview in Swiftui

How do you create a multi-line text inside a ScrollView in SwiftUI?

In Xcode 11 GM:

For any Text view in a stack nested in a scrollview, use the .fixedSize(horizontal: false, vertical: true) workaround:

ScrollView {
VStack {
Text(someString)
.fixedSize(horizontal: false, vertical: true)
}
}

This also works if there are multiple multiline texts:

ScrollView {
VStack {
Text(someString)
.fixedSize(horizontal: false, vertical: true)
Text(anotherLongString)
.fixedSize(horizontal: false, vertical: true)
}
}

If the contents of your stack are dynamic, the same solution works:

ScrollView {
VStack {
// Place a single empty / "" at the top of your stack.
// It will consume no vertical space.
Text("")
.fixedSize(horizontal: false, vertical: true)

ForEach(someArray) { someString in
Text(someString)
.fixedSize(horizontal: false, vertical: true)
}
}
}

Multiline text truncated in ScrollView

With the help of concepts from the answer from Tushar Sharma I was able to create a version that displays the multiline text and has a continuous divider between the two "columns".
The only changes are in SomeRow View (compared to my initial question):

struct SomeRow: View {
var entries: [Entry]

var body: some View {
VStack(alignment: .leading, spacing: 0){
Text("title").frame(maxWidth: .infinity, alignment: .leading)
Spacer().frame(height: 5)
ForEach(entries){entry in
HStack(alignment: .top){
VStack{
Text("00:00 - 00:00")
Spacer()
}.frame(minWidth: 110)
Divider()
VStack(alignment: .leading){
Text("titleinner")
HStack(alignment: .lastTextBaseline){
Text(entry.description ?? "")
Spacer()
Text("number")
}
Spacer()
}
Spacer()
}.fixedSize(horizontal: false, vertical: true)
}
}
}
}

Basically using specified alignments and using fixedSize on the whole container of the text works wonders.
This is how it looks like now:
somelistview

Trying to set up a scrollable view with multiple multiline of text but when app is run, it is running very slow when scrolling

I think the problem is with your padding()s. try removing them.

You should add padding to your views like this:

Text("content")
.padding()

as you can see in the documentation, padding(_) is a view modifier and should be called on a View.

to add extra space between your components, you can do either:

1- set the space between components of your LazyVStack by passing spacing like this:

LazyVStack(alignment: .leading, spacing: 32) { // <- spacing
Text("Main Screen")
.font(.title2)
.foregroundColor(.purple)
Text("This is the description text for the Main Screen")
.padding(.all)
.font(.title3)
.foregroundColor(.pink)
}.padding(.leading)

2- or set the top padding by using padding(_, _) modifier:

LazyVStack(alignment: .leading) {
Text("Main Screen")
.font(.title2)
.foregroundColor(.purple)
.padiing(.top, 32) // <-- padding
Text("This is the description text for the Main Screen")
.padding(.all)
.font(.title3)
.foregroundColor(.pink)
.padding(.top, 32) // <-- padding
}.padding(.leading)

How do I create a multiline TextField in SwiftUI?

Update: While Xcode11 beta 4 now does support TextView, I've found that wrapping a UITextView is still be best way to get editable multiline text to work. For instance, TextView has display glitches where text does not appear properly inside the view.

Original (beta 1) answer:

For now, you could wrap a UITextView to create a composable 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

Sample Image

Adding unlimited lines in a Text (SwiftUI)

For wrapping Text in a Form .lineLimit(Int.max) did not work for me. It seems there needs to be some width for it to know when to wrap. I believe the official way is with .fixedSize:

Text(message)
.fixedSize(horizontal: false, vertical: true)

The documentation states:

This example shows the effect of fixedSize(horizontal:vertical:) on a text view that is wider than its parent, preserving the ideal, untruncated width of the text view.

https://developer.apple.com/documentation/swiftui/view/fixedsize(horizontal:vertical:)



Related Topics



Leave a reply



Submit