UIButton doesn't listen to content mode setting?

IosUibuttonContentmode

Ios Problem Overview


firstButton is a UIButton of type Custom. I'm programmatically putting three of them across each cell of a table, thusly:

[firstButton setImage:markImage forState:UIControlStateNormal];
[firstButton setContentMode:UIViewContentModeScaleAspectFit];
[cell.contentView addSubview:firstButton];

Elsewhere, I'm telling it to clipToBounds. What I get is a crop of the center square of the image, rather than an aspect-scaled rendering of it. I've tried this lots of ways, including setting the mode property on firstButton.imageView, which also doesn't seem to work.

Ios Solutions


Solution 1 - Ios

I had the same problem. I see this question is a little old, but I want to provide a clear and correct answer to save other folks (like me) some time when it pops up in their search results.

It took me a bit of searching and experimenting, but I found the solution. Simply set the ContentMode of the "hidden" ImageView that is inside the UIButton.

[[firstButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[firstButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];

Perhaps that's what Dan Ray was alluding to in his accepted answer, but I suspect not.

Solution 2 - Ios

If you're dealing with the UIButton's image (as opposed to it's backgroundImage), setting the contentMode on the UIButton itself or on its imageView has no effect (despite what other answers say).

Alternatively do this instead:

self.button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
self.button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Or size your image accordingly.

OR just use a UIImageView (which properly respects contentMode) with a UITapGestureRecognizer attached to it, or a transparent UIButton on top of it.

Solution 3 - Ios

Rather than setting the contentMode on the button itself, you'll want to set contentHorizontalAlignment and contentVerticalAlignment properties and (crucially) the contentMode for the button's imageView for any kind of aspect fill or fit:

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

You can also do other things like aligning the button's image to the top. If you don't need an aspect fill or fit, you just can set the alignment by itself:

button.contentVerticalAlignment = .top

Solution 4 - Ios

After a couple of hours of confusion, here's how I got it to work under iOS 3.2. As dusker mentioned, using setBackgroundImage instead of setImage did the job for me.

CGRect myButtonFrame = CGRectMake(0, 0, 250, 250);
UIImage *myButtonImage = [UIImage imageNamed:@"buttonImage"];
    
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];

[myButton setBackgroundImage:myButtonImage forState:UIControlStateNormal];
[myButton setFrame: myButtonFrame];
[myButton setContentMode: UIViewContentModeScaleAspectFit];

Solution 5 - Ios

The answer is to use a UIImageView with all the lovely Content Mode settings you want, and then layer a custom button on top of it. Dumb that you can't do that all in one shot, but it appears that you can't.

Solution 6 - Ios

These two things (which are quite hard to find initially) will stretch your UIButton image to fit the button size:

enter image description here enter image description here

one should always try to set such in the Storyboard rather than code.

Solution 7 - Ios

Found a fix for this. Set the adjustsImageWhenHighlighted property of UIButton to NO.

  UIButton *b = [[UIButton alloc] initWithFrame:rect];
        [b setImage:image forState:UIControlStateNormal];
        [b.imageView setContentMode:UIViewContentModeScaleAspectFill];
        [b setAdjustsImageWhenHighlighted:NO];

Hope this helps. Feel free to comment below, I will follow up on any questions that you have.

Solution 8 - Ios

My answer is similar to Kuba's. I needed my image to be programatically set.

UIImage *image = [[UIImage alloc] initWithContentsOfFile:...];
[button setBackgroundImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill; //this is needed for some reason, won't work without it.
for(UIView *view in button.subviews) {
    view.contentMode = UIViewContentModeScaleAspectFill;
}

Solution 9 - Ios

Only solution which worked for me:

[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

Solution 10 - Ios

Swift 3

self.firstButton.imageView?.contentMode = .scaleAspectFill

Solution 11 - Ios

For anyone experiencing this on iOS 15 and Xcode 13, see Matt's answer in this other question.

The behavior of Xcode changed and now defaults UIButtons from the library to the plain style, which prevents the child image from scaling as expected.

Solution 12 - Ios

Instead of setImage try setBackgroundImage

Solution 13 - Ios

I believe we have a simple interface builder issue here - apparently the IB ignores any content-mode changes AFTER you have set the image-property.

the solution is as simple: set the content mode, remove previously set image-names (make sure you remove it in all states, default, highlighted etc.), then re-enter the desired image-names in all desired states - et voilĂ .

Solution 14 - Ios

I also advice to have a look at the adjustsImageWhenHighlighted UIButton property to avoid weird deformations of the image, when the button is pressed.

Solution 15 - Ios

In trying to figure this out, my method got a bit hackier as time went on, and I wound up subclassing UIButton and overriding setHighlighted:

For me it works to just knock down the image alpha to .5, because they're on a black background.

However, it only works if I comment out [super setHighlighted:] (where it appears the image-stretchy code is going on), which just doesn't feel like the right way to solve this at all...everything seems to be working fine, though. We'll see how it holds up as I keep working on it.

- (void)setHighlighted:(BOOL)highlight {
    if (highlight) {
        [self.imageView setAlpha:.5];
    }  else {
        [self.imageView setAlpha:1];        
    }

//    [super setHighlighted:highlight];
}

Solution 16 - Ios

If anyone looking for answer that work in iOS 6 and iOS 7 and storyboard:

You can set image in your storyboard:

enter image description here

And then:

for(UIView* testId in self.subviews) {
    if([testId isKindOfClass:[UIImageView class]])
        [testId setContentMode:UIViewContentModeScaleAspectFill];
}

Solution 17 - Ios

If the UIButton does not seem to listen to the layout constraint settings, do check whether the images are larger than the button size. Always use the @2x and @3x images for retina resolutions.

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
QuestionDan RayView Question on Stackoverflow
Solution 1 - IosDaveView Answer on Stackoverflow
Solution 2 - IosAlfie HanssenView Answer on Stackoverflow
Solution 3 - IosChris NoletView Answer on Stackoverflow
Solution 4 - IosPierreView Answer on Stackoverflow
Solution 5 - IosDan RayView Answer on Stackoverflow
Solution 6 - IosCorbin MillerView Answer on Stackoverflow
Solution 7 - IosiOSDevSFView Answer on Stackoverflow
Solution 8 - IosninjaneerView Answer on Stackoverflow
Solution 9 - IosTariqView Answer on Stackoverflow
Solution 10 - IosVaibhav SaranView Answer on Stackoverflow
Solution 11 - IosnaansequiturView Answer on Stackoverflow
Solution 12 - IosduskerView Answer on Stackoverflow
Solution 13 - IosJohnPayneView Answer on Stackoverflow
Solution 14 - IosMonsieurDartView Answer on Stackoverflow
Solution 15 - IosjankinsView Answer on Stackoverflow
Solution 16 - IosJakubView Answer on Stackoverflow
Solution 17 - IosTotoroView Answer on Stackoverflow