当UIButton的内容模式为“居中”时,背景图像会出现像素化问题。

15

这是我设置背景图片和内容模式的方法:

[btn setBackgroundImage:[UIImage imageNamed:@"dots_game_horiz_blue.png"] 
               forState:UIControlStateNormal];
[btn setContentMode:UIViewContentModeCenter];

背景图片变得像素化是有原因的吗?框架略大于图像尺寸,我只想让图像居中。


1
抱歉翻出这个古老的问题,但是如果我没有记错的话,那里有一个内存泄漏。分配未释放。 - Joseph Tura
5个回答

24

我猜背景图片在 UIButton 中不被认为是“内容”,所以内容模式不适用于背景图片。相反,我设置了按钮的图像,它正常工作:

[btn setImage:[[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"dots_game_horiz_blue" ofType:@"png"]] forState:UIControlStateNormal];
[btn setContentMode:UIViewContentModeCenter];

2
这个解决方案的问题在于UIButton有一个内部边距,因此如果图像不够小,即使它应该适合按钮内,它也会被裁剪。 - José Manuel Sánchez
3
在这里设置内容模式实际上并没有起到任何作用。按钮图像会自动居中且不会缩放。尝试将其设置为除居中以外的任何选项,你就会明白我的意思了。 - Ian Hoar
2
+1 不过,如果你想要同时拥有文本和图片,这种方法就不可行了 :-( - Marc
请注意,在界面构建器中设置内容模式不会影响预览,但在启动代码时将起作用。 - CedricSoubrie
这有点绕弯子,而不是一个真正的答案,因为问题明确指出了背景图片。 - Max MacLeod

10
在你的xib / storyboard中,在属性检查器中,你需要:
  1. 将你的UIButton类型设置为Custom
  2. Image属性中设置你的图像,而不是Background
  3. 验证步骤2,您可以看到按钮框架根据设置的图像而改变。将框架设置为所需大小,图像将自适应缩放以适应其中
  4. 选择Edge属性的Image选项以对按钮图像进行插图
  5. 输入所需的插图值。如果您将5设置为Top, Bottom, Left, Right,则图像将位于按钮内部居中,周围有5个边框

您可以在xib / storyboard视图中看到更改,无需启动调试。

提示:插图对于按钮的每个图像(State Config)都是相同的。


1
任何以“In your xib / storyboard”开头的内容都不是这个问题的解决方案:D - Magoo
到现在为止,解决方案已经发展。您可以通过尺寸检查器(规则图标)跳过步骤4并进行步骤5。 - Rémi Belzanti

5

您还可以实现- (CGRect)backgroundRectForBounds:(CGRect)bounds方法来控制背景的绘制。

该方法与界面元素的bounds属性相关联,您可以在其中定义要绘制的背景矩形。

3
这对我有用。我创建了一个自定义的UIButton类,并使用这段代码居中图片:- (CGRect)backgroundRectForBounds:(CGRect)bounds { UIImage *bkgImage = [self backgroundImageForState:self.state]; if (bkgImage) { CGFloat x = floorf((self.bounds.size.width-bkgImage.size.width)/2); CGFloat y = floorf((self.bounds.size.height-bkgImage.size.height)/2); return CGRectMake(x, y, bkgImage.size.width, bkgImage.size.height); } else return [super backgroundRectForBounds:bounds]; } - José Manuel Sánchez
在我看来,这是一种“过度设计”的解决方案。你可以简单地为按钮设置框架,例如: UIImage* img = [UIImage imageNamed:@"dots_game_horiz_blue.png"]; [btn setBackgroundImage:img forState:UIControlStateNormal]; btn.frame = CGRectMake(0, 0, img.size.width, img.size.height); - Tony

1
正确的解决方案是将类型从System更改为Custom。然后,背景图像将遵循内容类型而不仅仅是居中。在我的情况下,我将其设置为Aspect Fill并应用了45度圆角以使其变得圆润。简单而完美地解决了问题。

这个不起作用。我创建了一个新的自定义按钮,并将其内容模式设置为居中,但它仍然填充背景图像到视图的大小。 - devios1

0

我需要为头像照片创建圆形按钮,并找到了这个问题的答案来帮助我,但它们并没有完全解决我的问题。我实现了backgroundRectForBounds方法并缩放图像以适应,效果很好。

我已经将代码上传至GitHub。

https://github.com/brennanMKE/CircleButton

该方法如下所示。重要的是设置背景图像而不是按钮图像,因为该方法无法使用按钮图像。

- (CGRect)backgroundRectForBounds:(CGRect)bounds {
    UIImage *backgroundImage = [self backgroundImageForState:self.state];
    if (backgroundImage) {
        CGFloat maxWidth = CGRectGetWidth(self.frame);

        CGFloat xDelta = maxWidth / backgroundImage.size.width;
        CGFloat yDelta = maxWidth / backgroundImage.size.height;
        CGFloat delta = xDelta > yDelta ? xDelta : yDelta;

        CGFloat x = floorf((self.bounds.size.width - (backgroundImage.size.width * delta)) / 2);
        CGFloat y = floorf((self.bounds.size.height - (backgroundImage.size.height * delta)) / 2);

        return CGRectMake(x, y, backgroundImage.size.width * delta, backgroundImage.size.height * delta);
    }
    else {
        return [super backgroundRectForBounds:bounds];
    }
}

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