iosswiftuiwidgetkit

Fill Image with its content in SwiftUI


I am creating a Widget in SwiftUI and I'm finding what I believe is a very silly issue.

I have an Image that I want to use as a background. I have set its aspect ratio as .fill but it doesn't seem to do it.

Here's the code:

var body: some View {
        ZStack {
            Image(affirmation.customImageName ?? "c_0")
                .edgesIgnoringSafeArea(.all)
                .aspectRatio(contentMode: .fill)
                .frame(width: 300, height: 300, alignment: .center)
                .background(Color.green)
            
            HStack {
                VStack {
                    Text(affirmation.title)
                        .font(.title)
                        .multilineTextAlignment(.leading)
                }
                Spacer()
            }
            .padding(.leading, 5)
            .padding(.top, 5)
            
        }
    }

And how it looks: enter image description here

Also, if I delete .frame(width: 300, height: 300, alignment: .center), the image won't use the whole area.

UPDATED:

Now the image resizes thanks to @staticVoidMan answer, adding resizable() did the trick. The issue now is that the Text seems to also resize and fill more than its space.

var body: some View {
        ZStack {
           Image(affirmation.customImageName ?? "c_0")
           .resizable()
           .aspectRatio(contentMode: .fill)
            
            HStack {
                Text(affirmation.title)
                    .font(.body)
                    .multilineTextAlignment(.leading)
                    .lineLimit(nil)
                Spacer()
            }
            .padding(.leading, 5)
            .padding(.top, 5)
            
        }

Here's the image:

enter image description here

Thanks in advance


Solution

    1. .resizable is an Image view modifier that allows it to occupy the maximum amount of space required.

    2. ZStack by default can stretch indefinitely to fit all it's inner views and hence you need to define the frame via the .frame modifier so all the inner views stay within defined limits.

    i.e.

    ZStack {
        //...
    }
    .frame(width: 300, height: 300)
    

    Solution:

    ZStack(alignment: .leading) {
        Image("yourImageName")
            .resizable()
            .aspectRatio(contentMode: .fill)
            .background(Color.green)
        
        Text("Lorem ipsum dolor set amet")
            .font(.title)
            .padding(.leading, 5)
    }
    .frame(width: 300, height: 300)