Behold:
//UIImageView* stretchTest = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"image.png"]];
//[self addSubview:stretchTest];
UIButton *stretchTest = [UIButton buttonWithType:UIButtonTypeCustom];
[stretchTest setFrame:CGRectMake(0, 0, 400, 100)];
[stretchTest setBackgroundImage:[UIImage imageNamed:@"image.png"] forState:UIControlStateNormal];
[self addSubview:stretchTest];
stretchTest.contentStretch = CGRectMake(0.5, 0.5, 0, 0);
stretchTest.contentMode = UIViewContentModeScaleToFill;
CGRect frame = stretchTest.frame;
frame.size.height = 300;
stretchTest.frame = frame;
Using the UIImageView (commented out above), the image stretches appropriately - rounded corners maintain the correct radius, because only the center pixel of the image gets stretched.
Using the UIButton, the image gets stretched incorrectly. The corner radii are not maintained and it gets ugly.
Both UIImageView and UIButton are subclasses of UIView. Why does the button resize differently than the imageView?
You're making assumptions about the way UIButton works. It's not implemented the same way as UIImageView. UIImageView is just a view, with no subviews, and its contents is the image. UIButton is different, and the way it works is a private implementation detail.
If you're trying to stretch an image appropriately on a button, you should use
-[UIImage stretchableImageWithLeftCapWidth:topCapHeight:]
to get a UIImage that knows how it should be stretched. If you want to stretch just the middle pixel, you can use something likeA
UIButton
has two types of images it can display -- a foreground image and a background image. The background image for a button is expected to replace the button's background texture. As such, it will stretch to fill the entire background. The button's foreground image is expected to be an icon that may or may not display alongside text; it will not stretch. It may shrink if the frame is smaller than the image, but it will not stretch.A button's foreground and background image can be set in code like this:
By default, the
backgroundImage
of a button will use scaleToFill to stretch the image. If you need the image to stretch using cap insets though, you should set them on the image before assigning it to the backgroundImage, like this: