1

Here is a simple code that produces a strange top alignment and shrunk text of the second element inside ZStack.

BUT if you change the second text a bit (replace text2 by text2Alt1 or by text2Alt2) making it longer or shorter everything becomes correct.

What is the reason for this behavior?

struct VCardView: View {
    let text: String
    let color: UIColor
    
    var body: some View {
        VStack {
            Rectangle()
                .fill(Color(self.color))
                .frame(idealWidth: 800, idealHeight: 500)
                .aspectRatio(contentMode: .fit)

            Text(self.text)
        }
    }
}

struct ContentView: View {
    var body: some View {
        ZStack(alignment: .topLeading) {
            VCardView(text: text1, color: .blue)
                .frame(width: 180, height: nil)
                .alignmentGuide(.leading) { _ in 180 }
                .alignmentGuide(.top) { _ in 0 }
            
            //Replace text2 by text2Alt1 or text2Alt2 here:
            VCardView(text: text2, color: .green)
                .frame(width: 180, height: nil)
                .alignmentGuide(.leading) { _ in 0 }
                .alignmentGuide(.top) { _ in 0 }
        }
    }
    
    let text1 = "1Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidu!"
    
    let text2 = "2Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis nat!"
    
    
    let text2Alt1 = "2Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. C"
    
    let text2Alt2 = "2Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis nat! Cum sociis nat!"
}

Also, you could replace Rectangle() by Image() with appropriate proportions because it was the initial state. Rectangle with the ideal size is just for demonstration.

Here I use ZStack with explicit alignment guides (not HStack) because it's a part of another library. It is essential.

XCode 11.5 iOS 13.5 iPhone SE 2020

Bug looks like this:

Expected layout:

Phil Dukhov
  • 67,741
  • 15
  • 184
  • 220
Den Ob
  • 13
  • 5

2 Answers2

1

I've seen such Text truncation problems often in SwiftUI. The workaround which most of the time helps: ensure that Text is allowed to adjust it's font size automatically using the minimumScaleFactor modifier.

By modifying VCardView

Text(self.text)
    .minimumScaleFactor(0.5)

The misalignment problem disappears for all possible text values (text1, text2, text2Alt1 and text2Alt2).

The resulting text does not look scaled at all. Everything fits nicely. I do not have a good explanation, but I think if you tell SwiftUI that your Text is not 100% rigid/stiff, it performs better in calculating the elements extents.

Perhaps it is a SwiftUI bug, but I was always OK with this minimumScaleFactor workaround as it hadn't negatively impacted my results.

pd95
  • 1,999
  • 1
  • 20
  • 33
0

it doesn't look like a ZStack problem. Try to remove .aspectRatio(contentMode: .fit) from Rectangle() in VCardView.

For rectangle proportion check something like this.

Joannes
  • 2,569
  • 3
  • 17
  • 39
  • The idea is to save proportions based on the intrinsic size of the `Rectange()` view and fit to the parent view (limited by `.frame(width: 180, height: nil)`). Replace `Rectangle()` by `Image()` and remove `frame(idealWidth: idealHeight:)` for example. The result is the same and `GeometryReader` can't help you to read an image intrinsic size. – Den Ob Jun 01 '20 at 09:14