How can I make an Image with half of screen height in SwiftUI?

Viewed 3002

I would like to centre an image on the screen but make its height half of the screen height? How is this possible?

2 Answers

Like this, if you have a question about code ask plz, I think it is easy to understand.

import SwiftUI

struct ContentView: View {
    var body: some View {

        Image(systemName: "person")
            .resizable()
            .frame(width: UIScreen.main.bounds.height/2, height: UIScreen.main.bounds.height/2)
            .aspectRatio(contentMode: .fit)
    }
}

updated: for supporting orientation change:

import SwiftUI

struct ContentView: View {

@State var sizeOfImage: CGFloat = UIScreen.main.bounds.height/2

var body: some View {

    Image(systemName: "person")
        .resizable()
        .frame(width: sizeOfImage, height: sizeOfImage)
        .aspectRatio(contentMode: .fit)
        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
            sizeOfImage = UIScreen.main.bounds.height/2  }



    }
}

You can use a GeometryReader in SwiftUI to get details of a view's container geometry; Note that this approach is different to using the screen size, but this is a more flexible as you can use it inside other views.

struct RatioImage: View {
    let image: Image
    let heightRatio:CGFloat = 0.5
    
    var body: some View {
        GeometryReader { geo in
            VStack {
                Spacer()
                image.resizable().aspectRatio(contentMode: .fit)
                .frame(width: geo.size.width, height: geo.size.height*heightRatio, 
                       alignment: .center)
                Spacer()
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        HalfHeight {
            RatioImage(image: Image(systemName:"photo.fill"))
        }
    }
}

By using SwiftUI's ViewBuilder capability you can create a generic container that can resize arbitrary content:

struct RatioContainer<Content: View>: View {
    let heightRatio:CGFloat
    let content: Content

    init(heightRatio:CGFloat = 0.5,@ViewBuilder content: () -> Content) {
            self.heightRatio = heightRatio
            self.content = content()
    }

    var body: some View {
        GeometryReader { geo in
            VStack {
                Spacer()
            content.frame(width: geo.size.width, height: geo.size.height*heightRatio, alignment: .center)
                Spacer()
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        RatioContainer {
            VStack {
                Image(systemName: "photo").resizable().aspectRatio(contentMode: .fit)
                Text("Some caption text").font(.caption)
            }
        }
    }
}

You can even nest instances of the container, which won't work correctly if you use UIScreen dimensions:

struct ContentView: View {
    var body: some View {
        VStack {
            RatioContainer {
                VStack {
                    Image(systemName: "photo").resizable().aspectRatio(contentMode: .fit)
                    Text("Some caption text").font(.caption)
                    RatioContainer(heightRatio:0.3) {
                        VStack {
                            Image(systemName: "photo.fill").resizable().aspectRatio(contentMode: .fit)
                            Text("Some other caption text").font(.caption)
                        }
                    }
                    
                }
            }
            
        }
    }
}
Related