254

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)
Daniil Subbotin
  • 6,138
  • 5
  • 20
  • 24

25 Answers25

466

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

Image(room.thumbnailImage)
    .resizable()
    .frame(width: 32.0, height: 32.0)
Andrew_STOP_RU_WAR_IN_UA
  • 9,318
  • 5
  • 65
  • 101
rraphael
  • 10,041
  • 2
  • 25
  • 33
  • 12
    And how do you resize the image keeping the aspect ratio? – Mark Kang Jun 11 '19 at 11:22
  • 1
    @MarkKang I didn't try it, but there is a method named [`aspectRatio(_:contentMode:)`](https://developer.apple.com/documentation/swiftui/image/3269594-aspectratio) – rraphael Jun 11 '19 at 11:37
  • That method requires you to specify the aspect ratio. I would like to keep the original aspect ratio of the image but constrain it to best fit by frame height, centering the image content and cropping by the frame. – Mark Kang Jun 11 '19 at 12:03
  • @MarkKang I don't know if you can do that dynamically. One solution would be to hard code the aspect ratio of the actual image. – rraphael Jun 11 '19 at 12:12
  • 6
    Image("image01") .resizable() .aspectRatio(UIImage(named: "image01")!.size, contentMode: .fit) – Mark Kang Jun 11 '19 at 12:22
  • @MarkKang - my ver is: Image(person.photo).resizable().aspectRatio(contentMode: ContentMode.fit) – Alex Jun 13 '19 at 13:05
  • 1
    That would be nice. But I think there is a bug with fit. https://www.hackingwithswift.com/swiftui/how-to-adjust-the-way-an-image-is-fitted-to-its-space – Mark Kang Jun 13 '19 at 13:09
  • 31
    `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. – jemmons Jun 14 '19 at 00:57
  • 1
    `Image("name").resizable().scaledToFit()` does not keep the original aspect ratio for me – p8me Dec 27 '19 at 18:50
  • 2
    Value of type 'some View' has no member 'resizable' – Ben May 14 '21 at 22:19
  • @Ben the resizable modifier must come directly after the Image instantiation, as other modifiers likely return a generic View. – jnelson Jun 16 '23 at 05:20
111

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).

aheze
  • 24,434
  • 8
  • 68
  • 125
Confused Vorlon
  • 9,659
  • 3
  • 46
  • 49
  • 1
    This solution does not keep the original aspect ratio in my case. – p8me Dec 27 '19 at 18:50
  • @pm89 what size are your original and final image/view ? – Confused Vorlon Dec 29 '19 at 15:26
  • 1
    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. – p8me Dec 29 '19 at 23:38
  • For me it works like this including keeping the aspect ratio, thanks – laka Jun 01 '20 at 16:41
  • This keeps the aspect ratio for me, but doesn't respect the size-- i.e., I don't get a square image. – Chris Prince Nov 17 '20 at 05:23
  • @ChrisPrince - that's the point. This keeps the image aspect ratio - but _within_ a 200 by 200 'box' – Confused Vorlon Nov 17 '20 at 14:13
  • OH! Ok. I was mistaken on the original goal. My goal was to make a square image, cropping without distortion. But that changes the image aspect ratio. Thanks. – Chris Prince Nov 18 '20 at 16:33
  • 1
    @ChrisPrince I think scaledToFill() will do that for you – Confused Vorlon Nov 18 '20 at 17:15
  • The order is important. `.scaledToFit()` must precede the `.frame()` – Victor Alonso Barberan Sep 25 '22 at 09:28
35

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)
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
amp.dev
  • 410
  • 4
  • 16
33

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.)

Womble
  • 4,607
  • 2
  • 31
  • 45
  • 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 – Ky - Jul 09 '19 at 16:33
  • 2
    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... – p8me Dec 27 '19 at 18:58
12
struct AvatarImage: View {
    var body: some View {

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

    }
}
Amarshan
  • 301
  • 2
  • 9
9
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.

Sambit Das
  • 131
  • 1
  • 5
8

Another approach is to use the scaleEffect modifier:

Image(room.thumbnailImage)
    .resizable()
    .scaleEffect(0.5)
Luis Fer Garcia
  • 3,168
  • 3
  • 15
  • 13
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)
dinesh sharma
  • 577
  • 10
  • 20
6

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.

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)
Hanny
  • 1,322
  • 15
  • 20
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)
sudayn
  • 1,169
  • 11
  • 14
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
                    }
Dilip Tiwari
  • 1,441
  • 18
  • 31
cmlcrn17
  • 51
  • 1
  • 3
  • 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: https://stackoverflow.com/conduct – disp_name Apr 07 '20 at 15:55
5
Image(systemName: "person.fill")
  .font(.system(size: 13))

will also work if you are using systemName.

M1X
  • 4,971
  • 10
  • 61
  • 123
4

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
    }
}
Umair Khan
  • 993
  • 8
  • 14
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)
    }
   }
}
sachin jeph
  • 209
  • 2
  • 4
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()
Shawkath Srijon
  • 739
  • 1
  • 8
  • 17
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)
Ahmed Rajib
  • 67
  • 1
  • 4
3

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) 
Davencode
  • 75
  • 6
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 
Komal Gupta
  • 155
  • 5
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 
Al Mustakim
  • 480
  • 4
  • 11
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)

2

You also can use:

Image("Example")
   .scaleEffect(NumberWithSizeBetweenZeroAndOne)
MasterMind
  • 89
  • 7
2

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

Image(systemName: "nose")
        .font(.largeTitle)
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)
    }
-1

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)
Anubhav Singh
  • 905
  • 6
  • 5