KONG
KONG

Reputation: 7381

scale Image in an UIButton to AspectFit?

I want to add an image to a UIButton, and also want to scale my image to fit with the UIButton (make image smaller). Please show me how to do it.

This is what I have tried, but it does't work:

[self.itemImageButton setImage:stretchImage forState:UIControlStateNormal];
[self.itemImageButton setContentMode:UIViewContentModeScaleAspectFit];
UIImage *stretchImage = [updatedItem.thumbnail stretchableImageWithLeftCapWidth:0 topCapHeight:0];

Upvotes: 115

Views: 131819

Answers (17)

Omar N Shamali
Omar N Shamali

Reputation: 773

in xCode 13.4.1, configure Style to Default and State Config to Default

enter image description here

Upvotes: 8

Dave
Dave

Reputation: 7717

I had the same problem. Just set the ContentMode of the ImageView that is inside the UIButton.

[[self.itemImageButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[self.itemImageButton setImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal];

Upvotes: 209

Abedalkareem Omreyh
Abedalkareem Omreyh

Reputation: 2329

I have a method that does it for me. The method takes UIButton and makes the image aspect fit.

-(void)makeImageAspectFitForButton:(UIButton*)button{
    button.imageView.contentMode=UIViewContentModeScaleAspectFit;
    button.contentHorizontalAlignment=UIControlContentHorizontalAlignmentFill;
    button.contentVerticalAlignment=UIControlContentVerticalAlignmentFill;
}

Upvotes: 6

Qasim Mirza
Qasim Mirza

Reputation: 71

Swift 5.0

 myButton2.contentMode = .scaleAspectFit
 myButton2.contentHorizontalAlignment = .fill
 myButton2.contentVerticalAlignment = .fill

Upvotes: 5

Hamid Reza Ansari
Hamid Reza Ansari

Reputation: 1147

1 - clear Button default text (important)

2 - set alignment like image

3 - set content mode like image

enter image description here

Upvotes: 13

Tanguy G.
Tanguy G.

Reputation: 2303

The easiest way to programmatically set a UIButton imageView in aspect fit mode :

Swift

button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit

Objective-C

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

Note: You can change .scaleAspectFit (UIViewContentModeScaleAspectFit) to .scaleAspectFill (UIViewContentModeScaleAspectFill) to set an aspect fill mode

Upvotes: 69

Mobile Developer
Mobile Developer

Reputation: 5760

For Xamarin.iOS (C#):

    myButton.VerticalAlignment = UIControlContentVerticalAlignment.Fill;
    myButton.HorizontalAlignment = UIControlContentHorizontalAlignment.Fill;
    myButton.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;

Upvotes: 1

Ortwin Gentz
Ortwin Gentz

Reputation: 54101

Expanding on Dave's answer, you can set the contentMode of the button's imageView all in IB, without any code, using Runtime Attributes:

enter image description here

  • 1 means UIViewContentModeScaleAspectFit,
  • 2 would mean UIViewContentModeScaleAspectFill.

Upvotes: 14

nalexn
nalexn

Reputation: 10801

None of the answers here really worked for me, I solved the problem with the following code:

button.contentMode = UIViewContentModeScaleToFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

You can do this in the Interface Builder as well.

enter image description here

Upvotes: 129

gcamp
gcamp

Reputation: 14672

If you really want to scale an image, do it, but you should resize it before using it. Resizing it at run time will just lose CPU cycles.

This is the category I'm using to scale an image :

UIImage+Extra.h

@interface UIImage (Extras)
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
@end;

UIImage+Extra.m

@implementation UIImage (Extras)

- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

UIImage *sourceImage = self;
UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;

CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;

CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (!CGSizeEqualToSize(imageSize, targetSize)) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor) 
                scaleFactor = widthFactor;
        else
                scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image

        if (widthFactor < heightFactor) {
                thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        } else if (widthFactor > heightFactor) {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
}


// this is actually the interesting part:

UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width  = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if(newImage == nil) NSLog(@"could not scale image");


return newImage ;
}

@end

You can use it to the size you want. Like :

[self.itemImageButton setImage:[stretchImage imageByScalingProportionallyToSize:CGSizeMake(20,20)]];

Upvotes: 27

Rudolf Adamkovič
Rudolf Adamkovič

Reputation: 31486

The cleanest solution is to use Auto Layout. I lowered Content Compression Resistance Priority of my UIButton and set the image (not Background Image) via Interface Builder. After that I added a couple of constraints that define size of my button (quite complex in my case) and it worked like a charm.

Upvotes: 4

capikaw
capikaw

Reputation: 12976

This can now be done through IB's UIButton properties. The key is to set your image as a the background, otherwise it won't work.

enter image description here

Upvotes: 19

Tulleb
Tulleb

Reputation: 9206

If you simply want to reduce your button image:

yourButton.contentMode = UIViewContentModeScaleAspectFit;
yourButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

Upvotes: 8

Andy Poes
Andy Poes

Reputation: 1720

Background image can actually be set to scale aspect fill pretty easily. Just need to do something like this in a subclass of UIButton:

- (CGRect)backgroundRectForBounds:(CGRect)bounds
{
    // you'll need the original size of the image, you 
    // can save it from setBackgroundImage:forControlState
    return CGRectFitToFillRect(__original_image_frame_size__, bounds);
}

// Utility function, can be saved elsewhere
CGRect CGRectFitToFillRect( CGRect inRect, CGRect maxRect )
{
    CGFloat origRes = inRect.size.width / inRect.size.height;
    CGFloat newRes = maxRect.size.width / maxRect.size.height;

    CGRect retRect = maxRect;

    if (newRes < origRes)
    {
        retRect.size.width = inRect.size.width * maxRect.size.height / inRect.size.height;
        retRect.origin.x = roundf((maxRect.size.width - retRect.size.width) / 2);
    }
    else
    {
        retRect.size.height = inRect.size.height * maxRect.size.width / inRect.size.width;
        retRect.origin.y = roundf((maxRect.size.height - retRect.size.height) / 2);
    }

    return retRect;
}

Upvotes: 2

ruyamonis346
ruyamonis346

Reputation: 357

You just need to set content mode of UIButton imageview for three events. -

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateNormal];

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateHighlighted];

[cell.imgIcon setImage:[UIImage imageWithData:data] forState:UIControlStateSelected];

We have code for three event bcoz while highlighting or selecting if button size is SQUARE and image size is rectangle then it will show square image at the time of highlighting or selecting.

I am sure it will work for you.

Upvotes: -1

ninjaneer
ninjaneer

Reputation: 7031

I had problems with the image not resizing proportionately so the way I fixed it was using edge insets.

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);

Upvotes: 22

andrew
andrew

Reputation: 39

make sure that you have set the image to Image property, but not to the Background

Upvotes: 3

Related Questions