UIButton won't go to Aspect Fit in iPhone

IosIphoneUibuttonAspect Fit

Ios Problem Overview


I have a couple UIButtons, and in IB they're set to Aspect Fit, but for some reason they're always stretching. Is there something else you have to set? I tried all the different view modes and none of them work, they all stretch.

Ios Solutions


Solution 1 - Ios

The solution is to set the contentMode on the imageView property of the UIButton. The UIButton has to be created with custom type for this to work I believe (otherwise nil is returned for this property).

Solution 2 - Ios

This method worked for me very well.:

In Xib select the button and set user defined runtime attributes:

  • Key path: self.imageView.contentMode
  • Type: Number
  • Value: 1

Click here to see more clearly the solution

> We use number because you cant use enum there. But the UIViewContentModeScaleAspectFit is equal to 1.

Solution 3 - Ios

I've had that problem before. I solved it by putting my image in a UIImageView, where contentMode settings actually work, and putting a transparent custom UIButton over top of that.

EDIT: This answer is obsolete. See @Werner Altewischer's answer for the correct answer in modern versions of iOS.

Solution 4 - Ios

If you are doing this in Interface Builder, you can use the Runtime attributes inspector to set this directly without any code.

Set your Key Path on the button to be "imageView.contentMode" with a type of "Number" and a value of "1" (or whichever mode you would like).

imageview.contentMode = 1

Solution 5 - Ios

Use button's imageView for contentMode. Not directly on the button itself.

homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];

Solution 6 - Ios

If you put the image in an UIImageView behind the button, you'll loose the built-in functionality of the UIButton class, such as adjustsImageWhenHighlighted and adjustsImageWhenDisabled, and of course the ability to set different images for different states (without the hazzle of doing this yourself).

If we want to have an image unstreched for all control states, one approuch is to get the image using imageWithCGImage:scale:orientation, as in the following method:

- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {
	
	// Check which dimension (width or height) to pay respect to and
	// calculate the scale factor
	CGFloat imgRatio = img.size.width / img.size.height, 
			btnRatio = btn.frame.size.width / btn.frame.size.height,
			scaleFactor = (imgRatio > btnRatio 
						   ? img.size.width / btn.frame.size.width
						   : img.size.height / btn.frame.size.height;

	// Create image using scale factor
	UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
											 scale:scaleFactor
									   orientation:UIImageOrientationUp];
	return scaledImg;
}

To implement this we would write:

UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];

This should prevent the image from stretching in all control states. It worked for me, but let me know if it doesn't!

NOTE: Here we are addressing a problem relating to UIButton, but the insideButton: might as well be insideView:, or whatever one would like to fit the image into.

Solution 7 - Ios

I had this problem a while back. The issue I had was i was trying to apply this effect to the background UIButton which is limited and therefore means you cannot adjust it as easy.

The trick is to set it as just an image then apply @ayreguitar's technique and that should fix it!

UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];

Solution 8 - Ios

This worked for me

[button.imageView setContentMode:UIViewContentModeScaleAspectFit];

Thanks to @ayreguitar for his comment

Solution 9 - Ios

Here's an alternative answer in swift:

myButton.imageView?.contentMode = .ScaleAspectFit

Solution 10 - Ios

Combining together a few different answers into one solution-- create a button with a custom type, set the button's imageView contentMode property, and set the image for the button (not the background image, which will still scale to fill).

//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)

Solution 11 - Ios

ios 12. You need to add also the content Alignment

class FitButton: UIButton {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        
    }
    
    override func layoutSubviews() {
        self.imageView?.contentMode = .scaleAspectFill
        self.contentHorizontalAlignment = .fill
        self.contentVerticalAlignment = .fill
        super.layoutSubviews()
        
        
    }

}

Solution 12 - Ios

btn.imageView.contentMode = UIViewContentModeScaleAspectFit;

Solution 13 - Ios

This answer is based on @WernerAltewischer's answer.

To avoid having connect my button to an IBOutlet to execute the code on it, I subclassed UIButton's class:

// .h
@interface UIButtonWithImageAspectFit : UIButton
@end

// .m
@implementation UIButtonWithImageAspectFit

- (void) awakeFromNib {
    [self.imageView setContentMode:UIViewContentModeScaleAspectFit];
}

@end



Now create a custom button in your xib, and set its image (not the background image):

UIButtonWithImageAspectFit: create and set image


Then, set its class:

UIButtonWithImageAspectFit: set custom class

You're done!
Instead of
UIButton without image aspect fit
your button's image aspect fit is now as expected:
UIButton with image aspect fit

Solution 14 - Ios

UIView content modes apply to the corresponding CALayer's "content". This works for UIImageViews because they set the CALayer content to the corresponding CGImage.

drawRect: ultimately renders to the layer content.

A custom UIButton (as far as I know) has no content (the rounded-rect style buttons might be rendered using content). The button has subviews: the background UIImageView, the image UIImageView, and the title UILabel. Setting the contentMode on the subviews may do what you want, but messing around with the UIButton view hierarchy is a bit of a no-no.

Solution 15 - Ios

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

Solution 16 - Ios

Changing UIButton.imageView.contentMode does not worked for me.
I solved the problem by setting the image to 'Background' property.
You can add ratio constraint if you need

Solution 17 - Ios

This overlaps many of the other answers, but the solution for me was to

  • set the contentMode of the UIImageView for the button to .ScaleAspectFit – which can either be done in the ”User Defined Runtime Attributes” in Interface Builder (ie. self.imageView.contentMode, Number, 1) or in a UIButton subclass;
  • disable ”Autoresize Subviews”;
  • set ”Edge” to ”Image” and appropriate ”Top” and ”Bottom” values for ”Inset” (which might only be needed if you, like me, used a PDF as image).

Solution 18 - Ios

You can use imageWithCGImage as shown above (but without the missing parentheses).

Also... millions of non-4.0 phones won't work with that code at all.

Solution 19 - Ios

[button sizeToFit] worked for me.

Solution 20 - Ios

Similar to @Guillaume, I have created a subclass of UIButton as a Swift-File. Then set my custom class in the Interface Builder:

interface builder.

And here the Swift file:

import UIKit

class TRAspectButton : UIButton {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.imageView?.contentMode = .ScaleAspectFit
    }
}

Solution 21 - Ios

I had the same issue, but I couldn't get it to work (perhaps it's a bug with the SDK).

Eventually, as a workaround, I placed a UIImageView behind my button and set the options I wanted on that, then simply placed a blank UIButton on top of it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmartyView Question on Stackoverflow
Solution 1 - IosWerner AltewischerView Answer on Stackoverflow
Solution 2 - IosIstván StefánovicsView Answer on Stackoverflow
Solution 3 - IosDan RayView Answer on Stackoverflow
Solution 4 - IosaverydevView Answer on Stackoverflow
Solution 5 - IosAhmed ElashkerView Answer on Stackoverflow
Solution 6 - IosAlexander WallinView Answer on Stackoverflow
Solution 7 - IosJoe BarbourView Answer on Stackoverflow
Solution 8 - IosKaran AlangatView Answer on Stackoverflow
Solution 9 - IosJoão NevesView Answer on Stackoverflow
Solution 10 - IosSwindlerView Answer on Stackoverflow
Solution 11 - IosJoão NunesView Answer on Stackoverflow
Solution 12 - IosselabandView Answer on Stackoverflow
Solution 13 - IosGuillaumeView Answer on Stackoverflow
Solution 14 - Iostc.View Answer on Stackoverflow
Solution 15 - IosninjaneerView Answer on Stackoverflow
Solution 16 - IosSoohwan ParkView Answer on Stackoverflow
Solution 17 - IosplindbergView Answer on Stackoverflow
Solution 18 - IosAliceView Answer on Stackoverflow
Solution 19 - IosHilaView Answer on Stackoverflow
Solution 20 - IosMotineView Answer on Stackoverflow
Solution 21 - IosAnshu ChimalaView Answer on Stackoverflow