I followed ViewThatFits
tutorial mentioned here, to show and hide a text according to its length and the available space as follows:
struct ExpandableText: View {
let text: String
let initialLineLimit: Int
@State private var isExpanded = false
@State private var showButton = false
var button: Button<Text> {
if isExpanded {
return Button("Show less") {
isExpanded = false
}
} else {
return Button("Show more") {
isExpanded = true
}
}
}
var body: some View {
Text(text)
.lineLimit(isExpanded ? nil : initialLineLimit)
.background {
ViewThatFits(in: .vertical) {
Text(text)
.hidden()
Color.clear
.onAppear {
showButton = true
}
}
}
if showButton {
button
}
}
}
This works fine if I use a VStack
with ScrollView
like this (copy-paste the code to try it out):
struct ContentView: View {
var items = ["this is test text",
"this is test text this is test text",
" this is test text this is test text this is test text",
"this is test text this is test text this is test text this is test text",
"this is test text this is test text this is test text this is test text this is test text",
"this is test text this is test text this is test text this is test text this is test text this is test text",
"this is a small text",
"this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text",
"this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text",
"this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text",
"this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text this is test text",
]
var body: some View {
ScrollView {
LazyVStack(spacing: 0) {
ForEach(items, id: \.self) { item in
ExpandableText(text: item, initialLineLimit: 2)
.padding()
}
}
}
}
}
However, when I use a LazyVStack
instead of a VStack
the "show more / less" button appears incorrectly if I scroll up and down, I couldn't find a clue why's this happening with the LazyVStack
.