UIButton在iPhone上无法使用Aspect Fit。

112

我有几个UIButtons,在IB中它们被设置为Aspect Fit,但由于某种原因它们总是被拉伸。是否还需要设置其他内容?我尝试了所有不同的视图模式,但它们都会被拉伸。


@Werner Altesischer的答案是正确的。请进行相应的更改。 - Harshit Gupta
1
@marty 你是在设置背景图片还是普通图片?背景图片不支持此操作,只有普通图片可以。 - Juan Boero
21个回答

243

解决方案是在UIButtonimageView属性上设置contentMode。我相信必须使用自定义类型创建UIButton才能使此方法有效(否则该属性将返回nil)。


71
这个对我有用:[button.imageView setContentMode:UIViewContentModeScaleAspectFit]; - ayreguitar
2
这个对我也起作用,但如果我设置 adjustsImageWhenHighlighted=YES,当我点击按钮时图像会再次被拉伸。 - cduck
1
在iOS 6中,adjustsImage中的拉伸已经被消除。 - Ben Flynn
3
在 iOS 8 上,这对我来说实际上不起作用。最初的答案(将 imageView 放在透明按钮后面)效果最好。 - user1416564
7
在Swift的当下,button.imageView!.contentMode = UIViewContentMode.scaleAspectFit的意思是将按钮中图像的内容模式设置为“缩放适应”模式。 - Nestor
显示剩余5条评论

63

这种方法对我非常有效:

Xib 中选择按钮并设置用户定义的运行时属性:

  • 键路径: self.imageView.contentMode
  • 类型: 数字
  • 值: 1

点击此处以更清晰地查看解决方案

我们使用数字是因为您无法在那里使用枚举。 但是 UIViewContentModeScaleAspectFit 等于 1。


2
这也在设计时更新了界面构建器中的图像。非常好的解决方案。 - George Filippakos
伟大的解决方案,代码很少,运行得非常好,枚举基于内容模式列表项。 - Kross
你也可以添加一个扩展来使它变得更容易:extension UIButton { @IBInspectable var imageContentMode: Int { get {return imageView?.contentMode.rawValue ?? 0} set {imageView?.contentMode = UIViewContentMode(rawValue: newValue) ?? .scaleAspectFit} } } - Yonat
没有使用 selfimageView.contentMode 对我起作用了! - byJeevan

46

我以前也遇到过这个问题。我把我的图片放在UIImageView里,那里的contentMode设置实际上是有效的,并在其上方放置了一个透明的自定义UIButton

编辑:这个答案已经过时。在现代版本的iOS中,参见@Werner Altewischer的答案获得正确答案。


是的,我尝试过了,但现在无法让按钮适应图像。 - marty
你如何使用这种技术来管理按钮状态?似乎响应用户交互,如“高亮显示”,会是一场噩梦。 - SooDesuNe
3
也许在2.5年前回答这个问题时这是正确的方法,但现在你可以编辑UIButton的内部ImageView并在那里设置内容模式。请参见@Werner Altewischer的答案。 - Steve Haley

24
如果您正在使用Interface Builder,则可以使用Runtime属性检查器直接进行设置,而不需要任何代码。
将您的按钮上的Key Path设置为“imageView.contentMode”,类型为“Number”,值为“1”(或您想要的任何模式)。 imageview.contentMode = 1

17

使用按钮的imageView来设置contentMode,而不是直接在按钮上设置。

homeButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
homeButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
homeButton.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
[homeButton setImage:[UIImage imageNamed:kPNGLogo] forState:UIControlStateNormal];

6
如果您将图片放在按钮后面的UIImageView中,您将失去UIButton类的内置功能,例如adjustsImageWhenHighlightedadjustsImageWhenDisabled,当然还有设置不同状态下的不同图像的能力(无需自己处理)。
如果我们想要一个对所有控件状态都不拉伸的图像,一种方法是使用imageWithCGImage:scale:orientation获取图像,如以下方法所示:
- (UIImage *) getScaledImage:(UIImage *)img insideButton:(UIButton *)btn {

    // Check which dimension (width or height) to pay respect to and
    // calculate the scale factor
    CGFloat imgRatio = img.size.width / img.size.height, 
            btnRatio = btn.frame.size.width / btn.frame.size.height,
            scaleFactor = (imgRatio > btnRatio 
                           ? img.size.width / btn.frame.size.width
                           : img.size.height / btn.frame.size.height;

    // Create image using scale factor
    UIImage *scaledImg = [UIImage imageWithCGImage:[img CGImage]
                                             scale:scaleFactor
                                       orientation:UIImageOrientationUp];
    return scaledImg;
}

为了实现这个功能,我们需要编写以下代码:
UIImage *scaledImg = [self getScaledImage:myBtnImg insideButton:myBtn];
[myBtn setImage:scaledImg forState:UIControlStateNormal];

这应该可以防止在所有控件状态下图片被拉伸。我已经测试过了,但如果不行,请告诉我!

注意:我们在解决一个与UIButton有关的问题,但是insideButton:也可以是insideView:或任何想要将图像适配进去的控件。


6
我之前也遇到过这个问题。我的问题是尝试将此效果应用于背景UIButton,但该功能受限,因此意味着您不能轻松调整它。
诀窍是将其设置为仅图像,然后应用@ayreguitar的技术,这样就可以解决问题了!
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
[myButton setContentMode:UIViewContentModeScaleAspectFill];
[myButton setImage:@"myImage.png" forState:UIControlStateNormal];

4
这对我有效。
[button.imageView setContentMode:UIViewContentModeScaleAspectFit];

感谢@ayreguitar的评论。

4

将不同答案组合成一个解决方案:创建一个自定义类型的按钮,设置按钮的imageView contentMode属性,并为按钮设置图像(而不是背景图像,它仍将缩放以填充)。

//Objective-C:
UIImage *image = [UIImage imageNamed:"myImageName.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:image forState:UIControlStateNormal];
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

//Swift:
let image = UIImage(named: "myImageName.png")
let button = UIButton(type: .custom)
button.imageView?.contentMode = .scaleAspectFit
button.setImage(image, for: .normal)

4

以下是Swift的另一种解决方案:

myButton.imageView?.contentMode = .ScaleAspectFit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接