2

I would like the Image "Astronaut Meditation (Traced)" and the text "Levitate" to be aligned as in the prototype image, which is in the dimensions of an iPhone 13 pro max. How I want it to look Here is my ContentView code:

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack
        {
            //Background
            Image("Background")
                .edgesIgnoringSafeArea([.top])
            
            
                **//Meditating Astronaut
                Image("Astronaut Meditaton  (Traced)")
                    
                    .position(x: 102, y: 106)
                //Levitate
                Text("Levitate")
                    .font(.system(size: 34, weight: .semibold, design: .rounded))
                    .foregroundColor(Color.white)
                    .position(x: 110, y: 386)**
              
        }
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

I have included an image of how it is previewed on Xcode: How it looks in XCode

steeezyboy
  • 31
  • 4

3 Answers3

2

Use below code to achieve your actual desire design. Wrap your content in VStack and also add frame to background image for bind in your whole device with device width and height.

And also add Spacer() in VStack to occupy remains bottom space(For move view to up side).

ZStack {
        //Background
        Image("Background")
            .resizable()
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) //Here add frame to background image
            .edgesIgnoringSafeArea(.all)
        
        VStack { //Wrap your view in VStack
            //Meditating Astronaut
            Image("Astronaut Meditaton  (Traced)")
                .resizable()
                .frame(width: 100, height: 100)
                .padding(.top,20)
            //Levitate
            Text("Levitate")
                .font(.system(size: 34, weight: .semibold, design: .rounded))
                .foregroundColor(Color.white)
            
            Spacer() //Add Spacer to move view to upper side.
            
        }.padding(.top,UIApplication.shared.windows.first?.safeAreaInsets.top ?? 0 + 150) //Add padding with safe area to top side for upper space(suitable for all devices).
    }
1

Do not use static value alignment like position or offset because it’s not stable for all devices, instead just wrap your content inside VStack{} then you will achieve your desired design.

ZStack {
        //Background
        Image("Background")
            .edgesIgnoringSafeArea([.top])
        
        VStack { //start wrapping after background color image
            //Meditating Astronaut
            Image("Astronaut Meditaton  (Traced)")
            //Levitate
            Text("Levitate")
                .font(.system(size: 34, weight: .semibold, design: .rounded))
                .foregroundColor(Color.white)
        }
          
    }
Steven-Carrot
  • 2,368
  • 2
  • 12
  • 37
1

Like @tail said, you should avoid absolute position & offset, since it will vary from device to device. But if you do want to use them for some reason, you can add a alignment parameter to the ZStack and then use offset to get the desired outcome.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ZStack(alignment: .center) {
            //Background
            Image("Background")
                .ignoresSafeArea(edges: [.top])

            //Meditating Astronaut
            Image(systemName: "gear")
                .resizable()
                .frame(width: 150, height: 150)
                .offset(y: -150)
            //Levitate
            Text("Levitate")
                .font(.system(size: 34, weight: .semibold, design: .rounded))
                .offset(y: -50)
        }

    }
}

Even better way would be to use GeometryReader and work with relative values to the screen size:

import SwiftUI

struct ContentView: View {
    var body: some View {
        GeometryReader { geometry in
            ZStack(alignment: .center) {
                //Background
                Image("Background")
                    .ignoresSafeArea(edges: [.top])

                //Meditating Astronaut
                Image(systemName: "gear")
                    .resizable()
                    .frame(width: 150, height: 150)
                    .position(x: geometry.size.width / 2, y: geometry.size.height / 5)

                //Levitate
                Text("Levitate")
                    .font(.system(size: 34, weight: .semibold, design: .rounded))
                    // Position with offsetting by the size of image.
                    // Image frame 150 -> half is 75 + 25 for padding.
                    .position(x: geometry.size.width / 2, y: geometry.size.height / 5 + 100)
            }
            .frame(width: geometry.size.width, height: geometry.size.height)
        }
    }
}

With GeometryReader I would use absolute position and calculate the position of image with the relative values and then use the image size in addition to position the text

Iiro Alhonen
  • 352
  • 3
  • 19