58

Why does a custom UIButton image not resize with the button?

I set its view mode to Scale to Fill in Interface Builder, but unlike a UIImageView image, it doesn't respect that setting.

Am I looking in the wrong place or is it not possible?

Matt Becker
  • 2,338
  • 1
  • 28
  • 36
willc2
  • 38,991
  • 25
  • 88
  • 99
  • I found that though it doesn't scale the image in IB it does scale the image in runtime. – an0 Dec 10 '09 at 07:26
  • 3
    that's not necessarily true... if you have 80x80pixel img with a 60x60 pixel button, it will scale the button to match the image size whereas a lot of people want the opposite (scale the image to match the smaller button size)... see my reply to this post for proper code to do this: http://stackoverflow.com/questions/2658738/the-simplest-way-to-resize-an-uiimage/2890200#2890200 – iwasrobbed May 22 '10 at 23:58

11 Answers11

98

While this may not be quite what you're after - the background image does scale.

teabot
  • 15,358
  • 11
  • 64
  • 79
  • If I put the image in the background, I get the correct behavior so you solved it, thanks. – willc2 Jun 30 '09 at 11:40
  • 3
    If you are unwilling to use the background image (because say you want to use different images for different states), you need set the alignment property. See: http://stackoverflow.com/questions/1957317/how-do-i-scale-a-uibuttons-imageview/8179900#8179900 – Chris Nov 18 '11 at 08:59
  • 2
    what if you want it to scale to fit? then background image, which scales to fill, would not be appropriate – user102008 Jun 13 '12 at 18:33
  • 1
    ah, so not the image, but the *background image.* I will forget my name before forgetting this. –  Jun 26 '19 at 19:28
73

Try this:

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

In Swift:

button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
ajrlewis
  • 2,968
  • 3
  • 33
  • 67
Cao Huu Loc
  • 1,569
  • 15
  • 18
  • 1
    You saved my day! Bravo .. Also make sure button type is `custom` – Hyder Jun 12 '17 at 06:50
  • 1
    Worked for me - XCode 8, Swift 3, UIButton created by storyboard, vector/PDF image as button image – xaphod Jul 15 '17 at 17:53
  • 1
    This should be the accepted answer – setting the image as background gives a different behavior. E.g., it doesn't let you control the touch area (which, in case of a content image can be bigger than the image itself). – lazarevzubov Dec 13 '21 at 06:50
61

Remember to set Control Alignment settings for the button

here set Control Alignment settings for the button

drpawelo
  • 2,348
  • 23
  • 17
24

Inside Attribute Inspector first set Type "Custom" and Style "Default" then Set alignment Horizontal and Vertical both "fill".

enter image description here

Md Imran Choudhury
  • 9,343
  • 4
  • 62
  • 60
13

I know this is old, but I think that the correct answer is that you should set the content mode to the "hidden" UIImageView that is inside the UIButton:

button.imageView.contentMode = UIViewContentModeScaleAspectFill;

This will change the content mode for the images views of the images set with:

[button setImage:yourAwesomeImage forState:UIControlStateNormal]; 
//Or any other state
JP Illanes
  • 3,665
  • 39
  • 56
  • doesn't work for me :-( My images are still not stretched to fill the button width and height – Orion Edwards Sep 16 '14 at 10:36
  • Doesn't work on iOS8. Tried setting it before and after adding image to button. `self.button1.imageView.contentMode = UIViewContentModeScaleAspectFill;` Tried scaleAscpetFill and scaleToFill, no go. Cao Huu Loc's solution does work. – Martin Berger Apr 06 '15 at 16:43
11

Just do (From Design OR From Code):

From Design

  1. Open your xib OR Storyboard.
  2. Select button
  3. Inside Attribute Inspector (Right side) > In "Control" section > select last 4th option for both Horizontal and Verical.

[For Point#3: Change Horizontal and vertical Align to UIControlContentHorizontalAlignmentFill and UIControlContentVericalAlignmentFill]

From Code

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

Sandip Patel - SM
  • 3,346
  • 29
  • 27
  • 2
    Funny, in the XIB viewer it doesn't look scaled. In fact it blows up the button to a larger size, but then at run-time it's scaled to the size it ought to be. – Joe C Oct 26 '15 at 16:53
10

Interface Builder

To get images in UIButtons to scale the same way as UIViews in interface Builder follow these steps:

Select your UIButton and from the Identity Inspector add the following to User Defined Runtime Attributes:

imageView.contentMode Number 1

Where number is the enum number of contentMode, eg:

0 = Scale to fill 
1 = Aspect Fit 
2 = Aspect Fill
etc..

Then open the Attributes editor for your UIButton and under Control set the Alignment to Fill (last button on right) for both horizontal and vertical.

SWIFT 3

Note you can also do this in code with the following:

button.imageView?.contentMode = .scaleAspectFit
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
George Filippakos
  • 16,359
  • 15
  • 81
  • 92
2

Updating this post will full answer for Swift 5:

//Set button's image
let image = UIImage(systemName: "heart.fill") //Your image here
button.setImage(image, for: .normal)

//Optional: Remove background image if you added one on accident
button.setBackgroundImage(nil, for: .normal)

//Optional: Set button's title (displayed next to button's image)
button.setTitle(nil, for: .normal)

//The button's "content" includes the title label and image
//So we set the button's content to fill the button
//If title label is nil, the content will only show the image
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill

//Set button's image to desired content mode (aspectFit avoids distortion)
//This restricts the image from resizing to fill the entire content area
button.imageView?.contentMode = .scaleAspectFit
nicksarno
  • 3,850
  • 1
  • 13
  • 33
  • 1
    `button.contentVerticalAlignment = .fill button.contentHorizontalAlignment = .fill` does the job, thanks – Tai Le Nov 11 '20 at 03:49
0

Try setting the Clip subviews property in Interface Builder to true.

Hope that helps.

Dshutsi
  • 451
  • 3
  • 8
-1

The best solution I found so far in Swift 2.1 is the following:

self.imageButton.imageView?.clipsToBounds = true
self.imageButton.imageView?.contentMode = UIViewContentMode.ScaleAspectFit

This will scale the image so it has an aspect fit in the imageView.

Menno
  • 142
  • 8
-6

Just get a real UIimageview and place a UIbutton on top of it and via layout menu set it to back. Then you can scale your image properly.

Rene
  • 1