如何防止按钮的背景图像拉伸?

时间:2011-12-30 02:30:15

标签: ios cocoa-touch uiimageview uibutton uikit

我正在为UIView分配一个UIButtonTypeCustom UIButton,其背景图像小于按钮的框架。图像较小的原因是因为我试图为UIButton添加更多的“目标区域”。但是,图像会缩放到帧的整个大小,而不仅仅是图像的大小。

我尝试将UIButton和UIButton的imageView contentMode属性设置为“UIViewContentModeScaleAspectFit”,但没有运气,图像仍然被拉伸。

有没有办法按计划编写我想做的事情?

提前致谢!

12 个答案:

答案 0 :(得分:124)

很多人在按钮图像方面犯了同样的错误,然后跳过箍,试图使按钮按照预期的方式运行。让我们一劳永逸地清楚这一点:

UIButton有两种可以显示的图像 - 前景图像和背景图像。预期按钮的背景图像将替换按钮的背景纹理。因此,延伸以填充整个背景是有道理的。但是,按钮的前景图像应该是一个可能会或可能不会与文本一起显示的图标;它不会拉伸。如果框架小于图像,可能缩小,但它不会拉伸。您甚至可以使用Interface Builder中的Control对齐属性设置前景图像的对齐方式。

按钮的前景和背景图像可以用如下代码设置:

// stretchy
[self setBackgroundImage:backgroundImage forState:UIControlStateNormal];  

// not stretchy
[self setImage:forgroundImage forState:UIControlStateNormal]; 

答案 1 :(得分:8)

您无法访问背景imageView,,但有完全可行的解决方法:

编辑:我最初发布的内容有一个更好的解决方法。 您可以使用任何颜色创建 UIImage,然后调用-setBackgroundImage:forState.

请参阅bradley's回答,此处: https://stackoverflow.com/a/20303841/1147286


原始答案:

不是调用-setBackgroundImage:forState:,而是创建一个新的UIImageView并将其添加为按钮的子视图。

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];
  1. 创建imageview
  2. 设置内容模式和框架
  3. 我还设置了一个可识别的标签,这样当屏幕旋转时,我可以轻松地在按钮的子视图中找到我的自定义imageView并重置其框架
  4. 将其作为子视图添加到按钮
  5. 将按钮的正面imageView放在前面,这样我们的自定义imageView就不会重叠了
  6. 当按钮需要旋转时,只需按标签找到imageView并重置其框架:

    UIImageView *bgImageView = (UIImageView *)[button viewWithTag:99];
    [bgImageView setFrame:CGRectMake(0, 0, newWidth, newHeight)];
    

答案 2 :(得分:1)

可能使用按钮的标题插入内容的最简洁和最简单的方法。

您将图像设置为按钮图像,然后更改左侧标题插图以匹配减去图像宽度:

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

这会将文本移回到图像添加到左侧之前的位置。您也可以使用此值为您添加一些填充按钮。

答案 3 :(得分:0)

另一个考虑因素是BaseLine约束。如果您的按钮设置了此约束(通过布局上的多个控件描绘为水平或垂直线),则会导致图像在不拉伸基础按钮控件的情况下拉伸。如果您的按钮被正确约束(前导/尾随和顶部/底部空间等等),则删除BaseLine约束应该对布局没有影响,同时允许前景图像正确缩放到基础按钮形状。 / p>

答案 4 :(得分:0)

我想最简单的解决方案是使用UIImage的resizableImageWithCapInsets方法。使用UIEdgeInsetsMake配置空闲空间。

答案 5 :(得分:0)

也偶然发现了这个问题。

以编程方式添加图像,正如传单完全解释的那样,没有帮助:(

我有一个按钮100x40和图像100x100,它会显得挤压,不适合,因为人们会从“Aspect Fit”选项推断。实际上,没有那些视图选项有效。

我只需要重新缩放它以使其适合按钮,然后使用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];

答案 6 :(得分:0)

可能会帮助某人

button.subviews.first?.contentMode = .scaleAspectFit

答案 7 :(得分:0)

Zoltán Matók answer 的 Swift 版本

只是我的代码副本,使用 SnapKit 进行自动布局和语法糖然后用于初始化的库,它应该与正常的 Apple 编程布局方式类似。

   let backButton = UIButton(type: .custom).then { (button) in
        let image = UIImage(named: "backButtonIcon")?.withRenderingMode(.alwaysOriginal)
        let imageView = UIImageView(image: image)
        button.addSubview(imageView)
        imageView.snp.makeConstraints { (make) in
            make.center.equalTo(button.snp.center)
        }
        button.bringSubviewToFront(imageView)
        button.contentMode = .scaleAspectFit
        button.backgroundColor = .clear
        button.isUserInteractionEnabled = true
        button.isEnabled = true
        
        
        button.imageView?.contentMode = .scaleAspectFit
        button.imageView?.snp.makeConstraints({ (make) in
            make.height.width.equalTo(24)
        })
        button.snp.makeConstraints { (make) in
            make.height.width.equalTo(24)
        }
    }

答案 8 :(得分:0)

您可以使用 uibutton.imageView.contentMode 不拉伸:

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.frame = CGRectMake(posX, posY, widthButton, heightButton);
    [button setTitle:@"" forState:UIControlStateNormal];
    [button setImage:[UIImage imageNamed:@"imageNamed"] forState:UIControlStateNormal];
    [button setImage:[UIImage imageNamed:@"imageNamedHighlighted"] forState:UIControlStateHighlighted];
    button.imageView.contentMode = UIViewContentModeScaleAspectFit;
    [button addTarget:self action:@selector(functionMenu:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview: button];

答案 9 :(得分:-1)

Answerbot以正确和正确的方式回答问题。不要与操作系统作斗争,按照预期使用的东西总是很好的建议。但是,有时你需要打破规则。

我能够通过用黑色CAlayer覆盖它来掩盖放大的背景图像(不阻止它),然后再用适当调整大小的图像CAlayer重叠。这都是通过创建UIButton的子类并覆盖setHighlighted方法来完成的。

需要代码?

- (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;
    }
}  

这项工作的灵感来自here

答案 10 :(得分:-1)

很简单:

    ImageBn.imageView?.contentMode = .scaleAspectFit
    ImageBn.setImage(chosenImage, for: .normal)

答案 11 :(得分:-2)

您需要做的是将图像添加为UIImageView。

然后在其上面添加一个带有transperent背景的按钮(UIColor ClearColor),并带有所需的宽度和高度。