296

I have a large image in Assets.xcassets. How to resize this image with SwiftUI to make it small?

I tried to set frame but it doesn't work:

Image(room.thumbnailImage)
    .frame(width: 32.0, height: 32.0)

26 Answers 26

536

You should use .resizable() before applying any size modifications on an Image.

Image(room.thumbnailImage)
    .resizable()
    .frame(width: 32.0, height: 32.0)
Sign up to request clarification or add additional context in comments.

11 Comments

And how do you resize the image keeping the aspect ratio?
@MarkKang I didn't try it, but there is a method named aspectRatio(_:contentMode:)
Image("image01") .resizable() .aspectRatio(UIImage(named: "image01")!.size, contentMode: .fit)
Image("name").resizable().scaledToFit() isn't bugged, though. So you can wrap your image in a view, adjust the frame of the view to whatever size you need, then scaledToFit() will then make the image as big as it can be while keeping aspect ratio.
Value of type 'some View' has no member 'resizable'
|
123

How about this:

struct ResizedImage: View {
    var body: some View {
        Image("myImage")
            .resizable()
            .scaledToFit()
            .frame(width: 200, height: 200)
    }
}

The image view is 200x200, but the image maintains the original aspect ratio (rescaling within that frame).

9 Comments

This solution does not keep the original aspect ratio in my case.
@pm89 what size are your original and final image/view ?
Original aspect ratio is 3/2 and the result becomes 1/1 which stretches the image. This seems to be a SwiftUI bug. I ended up using the suggested method by Mark Kang in the comments under the accepted answer, Image(uiImage: image!).resizable().aspectRatio(image!.size, contentMode: .fill) where image is of type UIImage because Image type does not expose any size property.
For me it works like this including keeping the aspect ratio, thanks 👍
@ChrisPrince I think scaledToFill() will do that for you
|
41

In SwiftUI, use the .resizable() method to resize an image. By using .aspectRatio() and specifying a ContentMode, you can either "Fit" or "Fill" the image, as appropriate.

For example, here is code that resizes the image by fitting:

Image("example-image")
.resizable()
.aspectRatio(contentMode: .fit)

1 Comment

that's the same as scaleToFit()
35

Expanding on @rraphael's answer and comments:

As of Xcode 11 beta 2, you can scale an image to arbitrary dimensions, while maintaining the original aspect ratio by wrapping the image in another element.

e.g.

struct FittedImage: View
{
    let imageName: String
    let width: CGFloat
    let height: CGFloat

    var body: some View {
        VStack {
            Image(systemName: imageName)
                .resizable()
                .aspectRatio(1, contentMode: .fit)
        }
        .frame(width: width, height: height)
    }
}


struct FittedImagesView: View
{
    private let _name = "checkmark"

    var body: some View {

        VStack {

            FittedImage(imageName: _name, width: 50, height: 50)
            .background(Color.yellow)

            FittedImage(imageName: _name, width: 100, height: 50)
            .background(Color.yellow)

            FittedImage(imageName: _name, width: 50, height: 100)
            .background(Color.yellow)

            FittedImage(imageName: _name, width: 100, height: 100)
            .background(Color.yellow)

        }
    }
}

Results

Fitted images preserving aspect ratio

(For some reason, the image is showing as a bit blurry. Rest assured that the real output is sharp.)

2 Comments

You're probably seeing a blurry image on SO because you're using a high-DPI monitor. I put this on a regular-DPI monitor and it looks crisp
This keeps the original aspect ratio, only because the aspect ratio of the original image is 1 (the image is a square) and you are using .aspectRatio(1, ... . Not to say that any other solution here has worked for me so far...
13

You can resize images based on what you are using:

Image from Assets:

Image("logo")
  .resizable()
  .scaledToFill() // OR .scaledToFit()
  .frame(width: 40, height: 40, alignment: .center)

Image from remote url by using AsyncImage:

AsyncImage(url: URL(string: "https://example.com/icon.png"))
   .frame(width: 50, height: 50)

With placeholder:

AsyncImage(url: URL(string: "https://example.com/icon.png")) { image in
   image.resizable()
} placeholder: {
   ProgressView()
}
.frame(width: 50, height: 50)

Images from SF symbols:

by specifying font:

Image(systemName: "xmark")
   .font(.title)

By using frames:

Image(systemName: "xmark")
  .resizable()
  .scaledToFit()
  .frame(width: 40, height: 40, alignment: .center)

Comments

12
struct AvatarImage: View {
    var body: some View {

            Image("myImage")
                .resizable()
                .scaledToFill() // <=== Saves aspect ratio
                .frame(width: 60.0, height:60)
                .clipShape(Circle())

    }
}

Comments

10
Image(room.thumbnailImage)
    .resizable()
    .frame(width: 32.0, height: 32.0,alignment: .center)

In SwiftUI .resizable() attribute helps to resize an image. After that we can give some custom size.

Comments

8

Another approach is to use the scaleEffect modifier:

Image(room.thumbnailImage)
    .resizable()
    .scaleEffect(0.5)

Comments

7

Well, It's seems pretty easy in SwiftUI.

Following the demo they given : https://developer.apple.com/videos/play/wwdc2019/204

struct RoomDetail: View {
    let room: Room
    
    var body: some View {
        Image(room.imageName)
            .resizable()
            .aspectRatio(contentMode: .fit)
    }
}

Hope it helps.

Comments

6

If you want to use aspect ratio with resizing then you can use following code:

Image(landmark.imageName).resizable()
                .frame(width: 56.0, height: 56.0)
                .aspectRatio(CGSize(width:50, height: 50), contentMode: .fit)

Comments

6

Since we shouldn't hardcode/fix the image size. Here is a better way to provide range to adjust according to the screen's resolution on different devices.

Image("ImageName Here")
       .resizable()
       .frame(minWidth: 60.0, idealWidth: 75.0, maxWidth: 95.0, minHeight: 80.0, idealHeight: 95.0, maxHeight: 110.0, alignment: .center)
       .scaledToFit()
       .clipShape(Capsule())
       .shadow(color: Color.black.opacity(5.0), radius: 5, x: 5, y: 5)

Comments

6

By default, image views automatically size themselves to their contents, which might make them go beyond the screen. If you add the resizable() modifier then the image will instead automatically be sized so that it fills all the available space:

Image("example-image")
    .resizable()

However, that may also cause the image to have its original aspect ratio distorted, because it will be stretched in all dimensions by whatever amount is needed to make it fill the space.

If you want to keep its aspect ratio you should add an aspectRatio modifier using either .fill or .fit, like this:

Image("example-image")
    .resizable()
    .aspectRatio(contentMode: .fit)

Comments

6
Image(systemName: "person.fill")
  .font(.system(size: 13))

will also work if you are using systemName.

Comments

5

Note : My image name is img_Logo and you can change image name define image properties this:

 VStack(alignment: .leading, spacing: 1) {
                        //Image Logo Start
                        Image("img_Logo")
                            .resizable()
                            .padding(.all, 10.0)
                            .frame(width: UIScreen.main.bounds.width * 0.4, height: UIScreen.main.bounds.height * 0.2)
                        //Image Logo Done
                    }

1 Comment

I'd highly recommend you to write a brief text along with your code, some kind of explanation. Please have a look at the code of conduct here: stackoverflow.com/conduct
5

SwiftUI provided us .resizable() modifier that will let SwiftUI to resizes an image to fit its space

struct ContentView: View {
    var body: some View {
        Image("home")
            .antialiased(true) //for smooth edges for scale to fill
            .resizable() // for resizing
            .scaledToFill() // for filling image on ImageView
    }
}

Comments

4

As they said you have to use for resizing an Image on SwiftUI :

Call an image -> Image("somename") then, you add -> .resizable()

and now the image is resizable

next you can apply .aspectRatio to fit dimension or just fill the frame.

Example for simple usage of resizable:

Image("somename")
.resizable()
.frame(width: 50px, height: 50px) 

Comments

4

Use the font modifier with a dynamic type on an Image view:

Image(systemName: "nose")
    .font(.largeTitle)

Comments

3

If you want to resize the image in swiftUI just use the following code :

import SwiftUI

    struct ImageViewer : View{
        var body : some View {
            Image("Ssss")
            .resizable()
            .frame(width:50,height:50)
        }
    }

But here is problem with this. If you add this Image inside a Button, the Image will not be shown, just a block of blue colour would be there. To solve this issue, just do this :

import SwiftUI

struct ImageViewer : View{
    var body : some View {
        Button(action:{}){
        Image("Ssss")
        .renderingMode(.original)
        .resizable()
        .frame(width:50,height:50)
    }
   }
}

Comments

3

It is very important to understand logical structure of code. Like in SwiftUI an image is not resizable by default. Thus, to resize any image you have to make it resizable by applying the .resizable() modifier immediately after you declare an Image view.

Image("An Image file name")
    .resizable()

Comments

3

To make an image scales to fit the current view, we use the resizable() modifier, which resizes an image to fit available space.

for Example:

 Image("ImageName")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 200, height: 200, alignment: .center)

1 Comment

This has already been explained in other answers, nothing new here.
2

You can define Image Properties as follow:-

   Image("\(Image Name)")
   .resizable() // Let you resize the images
   .frame(width: 20, height: 20) // define frame size as required
   .background(RoundedRectangle(cornerRadius: 12) // Set round corners
   .foregroundColor(Color("darkGreen"))      // define foreground colour 

Comments

2

Use .resizable() method after image name. Make sure usage of .resizable() need to declare before any modification.

like this:

Image("An Image file name")
    .resizable()
//add other modifications here 

Comments

2

It is suggested to use the following code to match multiple screen sizes:

Image("dog")
    .resizable()
    .frame(minWidth: 200, idealWidth: 400, maxWidth: 600, minHeight: 100, idealHeight: 200, maxHeight: 300, alignment: .center)

Comments

2

You also can use:

Image("Example")
   .scaleEffect(NumberWithSizeBetweenZeroAndOne)

Comments

1

You can use resizable() property, but keep it in mind that you cannot use resizable in a common modifier so you have to use Image extension to achieve it.

extension Image {
    func customModifier() -> some View {
        self
            .resizable()
            .aspectRatio(contentMode: .fit)
    }

Comments

-2

To resize an image in SwiftUI you need to use the .resizable() modifier before using the .frame() modifier

Image("imageName")
    .resizable()
    .frame(width: 20, height: 20)

4 Comments

This is essentially the same as the accepted answer.
Ok, so if the answer is same thn you tag as not useful answer?? @adamjansch
This answer is unnecessary, it just adds noise to an already busy SO question.
Ok, I will try to not repeat this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.