I'm tracing down a swiftUI text layout issue and created a small sample app reproducing it (tested on iOS 15, iPhone max size simulator) which I've filed as a radar. Looking for a workaround until it is fixed. NavigationView, List and PlainListStyle are the important ingredients.
Edit:
Expected Behaviour: text height adjusted appropriately and there is no text truncation. The presence of slider doesn't effect things.
Actual Behaviour: text height is not adjusted appropriately and there is text truncation. Uncommenting slider magically fixes the bug.
import SwiftUI
class Model: ObservableObject {
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
private var on = false
init() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
on.toggle()
value = on ? 0.99 : 0
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
NavigationView {
List {
// Uncomment - and there is no bug
// Slider(value: $model.value)
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
}
}
.listStyle(PlainListStyle())
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
@main
struct TextBugApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
import SwiftUI
class Model: ObservableObject {
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
private var on = false
init() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
on.toggle()
value = on ? 0.99 : 0
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
NavigationView {
List {
// Uncomment - and there is no bug
// Slider(value: $model.value)
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
}
.listStyle(PlainListStyle())
}
}
}
I think the fact you are duplicating HStack/Text makes it redraw twice and correct any incorrectness that would otherwise surface... try this to see the issue:
import SwiftUI
class Model: ObservableObject {
@Published var id = 0
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
private var on = false
init() {
Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [self] _ in
on.toggle()
value = on ? 0.99 : 0
id += 1
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
NavigationView {
List {
// Uncomment - and there is no bug
// Slider(value: $model.value)
HStack() {
Color.green.frame(width: model.value * 200, height: 1)
Text(model.text)
.fixedSize(horizontal: false, vertical: true)
}
.id(model.id)
// HStack() {
// Color.green.frame(width: model.value * 200, height: 1)
// Text(model.text)
// .fixedSize(horizontal: false, vertical: true)
// }
Color.blue
}
.listStyle(PlainListStyle())
}
}
}
class Model: ObservableObject {
@Published var value: CGFloat = 0
@Published var text = "t in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis"
var id: String {
String(Double(value)) + text
}