2

I use a ZStack to display a fullscreen background image underneath the main UI. The main UI consists of a VStack with multiple views separated by flexible Spacers to scale down or up on different device sizes. Now I experience that the Spacers will not scale down on small devices because the background image on small devices remains bigger than the screen size and keeps the ZStack tall, see screenshot of the preview of iPhone 8. What am I doing wrong here?

Code:

import SwiftUI

struct TestView: View {
    
    var headerView: some View {
        VStack {
            Text("HEADER").padding([.leading,.trailing], 100)
        }
    }
    
    var middleView: some View {
        HStack {
            Text("MIDDLE").padding([.leading,.trailing], 100)
        }
    }
    
    var bottomView: some View {
        VStack {
            Text("BOTTOM").padding([.leading,.trailing], 100)
        }
    }
    
    var body: some View {
        ZStack {
            // Background Image
            Image("BgImg")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .edgesIgnoringSafeArea(.all)
            
            // Main UI
            VStack(spacing: 0) {
                headerView
                    .frame(height:222)
                    .background(Color.red)
                
                Spacer()
                
                middleView
                    .frame(height:155)
                    .background(Color.orange)
                
                Spacer()
                
                bottomView
                    .frame(height:288)
                    .background(Color.yellow)
            }
            .padding(.bottom, 32)
            .padding(.top, 54)
            // END Main UI
        }
        .edgesIgnoringSafeArea(.all)
        .statusBar(hidden: true)
        // END ZStack
    }
}

Preview Screenshot: See blue border is bigger than device enter image description here

BG Image: enter image description here

FrankZp
  • 2,022
  • 3
  • 28
  • 41

1 Answers1

2

In described scenario you need to use .background instead of ZStack, such so main view form needed full-screen layout and image in background will not affect it.

So the layout should be like

VStack(spacing: 0) {

   // content here

}
.padding(.bottom, 32)
.padding(.top, 54)
.edgesIgnoringSafeArea(.all)
.statusBar(hidden: true)
.background(

     // image here

)
Asperi
  • 228,894
  • 20
  • 464
  • 690
  • Thanks for your reply. This indeed will keep the VStack unaffected by the background image size. However, I have problems to get the background image scaled to fullscreen. On iPhone 13 Pro it has a white border on the left and on iPhone 8 it has a white border left and right. – FrankZp Jan 24 '22 at 10:54
  • Works fine here. You have many hardcoded sizes which are incompatible with some form-factors. Try to avoid hardcoding (except minimal paddings) and then everything will fit on any device. – Asperi Jan 24 '22 at 11:13
  • it seems to be due to the image size and the aspect ratio. While the iPhone 13 Pro and newer devices have an aspect ratio of 19.5:9, the iPhone 8 has an aspect ratio of 16:9 and hence the image is not filling the screen properly. I was able to fix that with putting .frame(maxWidth: .infinity) above the .background modifier – FrankZp Jan 24 '22 at 12:17
  • I would also put the safe edge modifier on the background view, rather than on the VStack and then adjusting padding to replicate the safe area. If a VStack edge hits the safe area boundary, the background will then automatically expand into the safe area without having to worry about specific padding values. – ScottM Jan 24 '22 at 12:31