How to prevent stretching the background image of a button?

I highlight the UIButtonTypeCustom UIButton for the UIView with a background image that is smaller than the button frame. The reason the image is smaller is because I am trying to add more “target area” for UIButton. However, the image is scaled to the full frame size, and not just the image size.

I tried to set the UIButton and UIButton imageView contentMode values ​​to "UIViewContentModeScaleAspectFit", but not luck, the image is still stretched.

Is there a way to do what I'm trying to do programmatically?

Thanks in advance!

+45
ios cocoa-touch uikit uibutton uiimageview
Dec 30 '11 at 2:30
source share
9 answers

Many people make the same mistake as for button images, and then jump through hoops, trying to make the button behave as they expect it to. Let it expose once and for all:

A UIButton has two types of images that it can display - a foreground image and a background image . The background image for the button is supposed to replace the button's background texture. Thus, it makes sense that it is stretched to fill the entire background. However , the foreground image of the button should be an icon that may be displayed next to the text or not displayed; he will not stretch. It may contract if the frame is smaller than the image, but it does not stretch. You can even set the alignment of the foreground image using the alignment control properties in Interface Builder.

The foreground button and background image can be set in the code as follows:

 // stretchy [self setBackgroundImage:backgroundImage forState:UIControlStateNormal]; // not stretchy [self setImage:forgroundImage forState:UIControlStateNormal]; 
+117
Oct 26 '12 at 20:11
source share

You do not have access to the imageView background , but there is a fully working workaround:

EDIT : There is an even better workaround than what I originally posted. You can create a UIImage from any color and call -setBackgroundImage:forState.

See bradley's answer, here: https://stackoverflow.com/a/166778/




Original answer:

Instead of calling -setBackgroundImage:forState: create a new UIImageView and add it as a sub-item of the button.

 UIImageView *bgImageView = [[UIImageView alloc] initWithImage:img]; bgImageView.contentMode = UIViewContentModeScaleAspectFit; [bgImageView setFrame:CGRectMake(0, 0, videoButton.frame.size.width, videoButton.frame.size.height)]; bgImageView.tag = 99; [yourButton addSubview:bgImageView]; [yourButton bringSubviewToFront:yourButton.imageView]; 
  • Image creation
  • Set content mode and frame
  • I also set a recognizable tag, so that when the screen rotates, I can easily find my own image in the button view and reset its frame
  • Add it as a sub item to the button
  • Provide a front image Note of the button on the front panel so that our custom image does not overlap it.

When you need to rotate the button, just find the View image by its tag and reset its frame:

 UIImageView *bgImageView = (UIImageView *)[button viewWithTag:99]; [bgImageView setFrame:CGRectMake(0, 0, newWidth, newHeight)]; 
+6
Jul 12 '14 at
source share

The cleanest and easiest way is probably to use a button name insert.

You set your image as the button image, and then you change the insertion of the left caption to fit minus the width of your image:

 myButton.titleEdgeInsets = UIEdgeInsetsMake(0, -myImage.width, 0, 0) 

This will move the text back to where it was before the image was added on the left. You can also use this value to add an add button to you.

+1
May 29 '14 at 14:37
source share

Another consideration is the limitation of BaseLine. If this restriction is set on your buttons (displayed as a horizontal or vertical line with several controls on your layout), this will cause your images to stretch without stretching the basic control of the buttons. If your button is otherwise properly bounded (leading / trailing and upper / lower spaces, etc.), removing the BaseLine constraint should not affect the layout, allowing the correct foreground image to scale the main shape of the button.

0
Sep 11 '13 at 14:36
source share

I think the easiest solution is to use the UIImage resizableImageWithCapInsets method. Use UIEdgeInsetsMake to configure free spaces.

0
Jan 24 '14 at 2:33
source share

Stumbled upon this problem.

Adding an image programmatically, as memmons explained in detail, did not help :(

I had a 100x40 button and a 100x100 image, it would look compressed rather than installed, as it would be possible to conclude from the "Aspect Fit" option. In fact, the wrong viewing options had an effect.

I just had to re-scale it to fit on the button, and then use setImage:

 UIImage *img=[UIImage imageNamed:@"myimage.png"]; CGImageRef imgRef = [img CGImage]; CGFloat imgW = CGImageGetWidth(imgRef); CGFloat imgH = CGImageGetHeight(imgRef); CGFloat btnW = myBttn.frame.size.width; CGFloat btnH = myBttn.frame.size.height; //get lesser button dimension CGFloat minBtn=btnW; if (btnW>btnH) { minBtn=btnH; } //calculate scale using greater image dimension CGFloat scl=imgH/minBtn; if (imgW>imgH) { scl=imgW/minBtn; } //scale image UIImage *scaledImage = [UIImage imageWithCGImage:[img CGImage] scale:(img.scale * scl) orientation:(img.imageOrientation)]; //clean up UIGraphicsEndImageContext(); //set it on a button [myBttn setImage:scaledImage forState:UIControlStateNormal]; 
0
Jan 28 '16 at 19:39
source share

It's simple:

  ImageBn.imageView?.contentMode = .scaleAspectFit ImageBn.setImage(chosenImage, for: .normal) 
0
Aug 22 '17 at 7:09 on
source share

Answerbot answers the question of what is right and right to do. Do not fight with the OS and do not use things for their intended purpose, this is always good advice. However, sometimes you need to break the rules.

I managed to mask the enlarged background image (not disturb it) by overlaying it on a black CAlayer and then overlaying it again using a properly configured CAlayer image. All this was done by subclassing UIButton and overwriting the setHighlighted method.

CODE NEEDED:

 - (void)setHighlighted:(BOOL)highlighted { super.highlighted = highlighted; // //Whenever an image needs to be highlighted, create a dimmed new image that is correctly sized. Below it is a englarged stretched image. // if (highlighted != _previousHighlightedSate) { _previousHighlightedSate = highlighted; if (highlighted) { //Create a black layer so image can dim _blackLayer = [CALayer layer]; _blackLayer.bounds = self.bounds; CGRect rect = _blackLayer.bounds; rect.size.width = rect.size.width*2; rect.size.height = rect.size.height*2; _blackLayer.bounds = rect; _blackLayer.backgroundColor = [[UIColor blackColor] CGColor]; //create image layer _nonStretchImageLayer = [CALayer layer]; _nonStretchImageLayer.backgroundColor = [UIColor blackColor].CGColor; _nonStretchImageLayer.bounds = CGRectMake(0 , 0, self.bounds.size.width, self.bounds.size.height); _nonStretchImageLayer.frame = CGRectMake(0 , 0, self.bounds.size.width, self.bounds.size.height); _nonStretchImageLayer.contentsGravity = kCAGravityResizeAspect;//default is to resize _nonStretchImageLayer.contents = (id)self.imageView.image.CGImage; _nonStretchImageLayer.opacity = 0.5; //add layers to image view [self.imageView.layer addSublayer:_blackLayer]; [self.imageView.layer addSublayer:_nonStretchImageLayer]; } else { //remove from image view [_blackLayer removeFromSuperlayer]; [_nonStretchImageLayer removeFromSuperlayer]; //nil them out. _blackLayer = nil; _nonStretchImageLayer = nil; } } 

The inspiration for this work came from here.

-one
Sep 30 '13 at 9:18
source share

What you need to do is add the image as a UIImageView.

Then add a button with a transparent background (UIColor ClearColor) on top of it with the desired width and height.

-2
Sep 05
source share



All Articles