在UIButton中将图像缩放到AspectFit?


94

我想将图像添加到UIButton,也想缩放图像以适合UIButton(使图像变小)。请告诉我该怎么做。

这是我尝试过的方法,但是不起作用:

  • 将图像添加到按钮并使用setContentMode
[self.itemImageButton setImage:stretchImage forState:UIControlStateNormal];
[self.itemImageButton setContentMode:UIViewContentModeScaleAspectFit];
  • 制作“拉伸图像”:
UIImage *stretchImage = [updatedItem.thumbnail stretchableImageWithLeftCapWidth:0 topCapHeight:0];

我认为这已更改为固件4.0及更高版本中的默认行为。
2011年

1
有关解决方案,请参见stackoverflow.com/a/28205566/481207
马特

Answers:


28

如果您确实要缩放图像,请执行此操作,但是在使用前应调整其大小。在运行时调整它的大小只会丢失CPU周期。

这是我用来缩放图像的类别:

UIImage + Extra.h

@interface UIImage (Extras)
- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize;
@end;

UIImage + Extra.m

@implementation UIImage (Extras)

- (UIImage *)imageByScalingProportionallyToSize:(CGSize)targetSize {

UIImage *sourceImage = self;
UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;

CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;

CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

if (!CGSizeEqualToSize(imageSize, targetSize)) {

        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor < heightFactor) 
                scaleFactor = widthFactor;
        else
                scaleFactor = heightFactor;

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image

        if (widthFactor < heightFactor) {
                thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        } else if (widthFactor > heightFactor) {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
}


// this is actually the interesting part:

UIGraphicsBeginImageContextWithOptions(targetSize, NO, 0);

CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width  = scaledWidth;
thumbnailRect.size.height = scaledHeight;

[sourceImage drawInRect:thumbnailRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

if(newImage == nil) NSLog(@"could not scale image");


return newImage ;
}

@end

您可以根据需要使用它。喜欢 :

[self.itemImageButton setImage:[stretchImage imageByScalingProportionallyToSize:CGSizeMake(20,20)]];

感谢您的回答,Gcamp。我确实有一种按比例调整大小的方法。但是我仍然尝试寻找一种方法来告诉UIButton为我做。我的图像是从Internet加载的,因此在编译时无法调整其大小。顺便说一句,非常感谢您的答复。
KONG 2010年

2
由于图像是放置在CALayer中,由Quartz渲染和缓存的,因此,如果将其以原尺寸放置在其中,性能不会变差。无论哪种方式,您都需要调整〜1倍的时间。如果您不断调整按钮的大小或执行其他会触发Quartz重绘图像层的操作,则gcamp的答案就更为重要。
Ben Gotow 2011年

好像图像质量下降了。我正在iPhone 6 Plus上进行测试。是真的吗 我也有3倍的图像。
Khant Thu Linn 2015年

是的,它将很旧。这是UIGraphicsBeginImageContext不是UIGraphicsBeginImageContextWithOptions。修复它。
gcamp

是的,但是在很多情况下,放松几个周期都没关系,所以填满公羊毫无意义
Radu Simionescu

203

我有同样的问题。只需设置UIButton内的ImageView的ContentMode。

[[self.itemImageButton imageView] setContentMode: UIViewContentModeScaleAspectFit];
[self.itemImageButton setImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal];

希望这可以帮助。


14
确保设置了imageView。我也没有注意到,我仍然在使用backgroundImageView,并且它没有用。
亚历山大亚历山大·戈麦斯

2
当按钮状态为“突出显示”时,此方法似乎存在一些问题。图像将返回到填充模式。任何想法?
Yuanfei Zhu

它对我不起作用。但是,我通过使用[self.itemImageButton setbackgroundImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal]使它起作用。
米奇

3
这对我有用。我如上所述设置了内容模式。但是,您还需要设置突出显示状态的相同图像,以避免图像返回“填充模式”。例如,[imageButton setImage:image forState:UIControlStateHighlighted];
Christopher

1
您可以在Interface Builder中使用关键路径imageView.contentMode,类型Number和值来做到这一点1
bentytree

107

这里没有任何答案对我真正有用,我使用以下代码解决了这个问题:

button.contentMode = UIViewContentModeScaleToFill;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;

您也可以在Interface Builder中执行此操作。

在此处输入图片说明


5
这不会给您OP要求的宽高比行为。
Ortwin Gentz '16

3
@OrtwinGentz您可以选择模式并进行设置,Aspect fit而不是scale to fill
丹尼尔(Daniel)

55

宽高比适合模式下以编程方式设置UIButton imageView的最简单方法:

迅速

button.contentHorizontalAlignment = .fill
button.contentVerticalAlignment = .fill
button.imageView?.contentMode = .scaleAspectFit

物镜

button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentFill;
button.contentVerticalAlignment = UIControlContentVerticalAlignmentFill;
button.imageView.contentMode = UIViewContentModeScaleAspectFit;

注意:可以将.scaleAspectFit(UIViewContentModeScaleScaleAspectFit)更改为.scaleAspectFill(UIViewContentModeScaleAspectFill)以设置外观填充模式


20

我遇到了图像无法按比例调整大小的问题,因此我修复图像的方法是使用边缘插图。

fooButton.contentEdgeInsets = UIEdgeInsetsMake(10, 15, 10, 15);

16

现在,可以通过IB的UIButton属性完成此操作。关键是将图像设置为背景,否则将无法使用。

在此处输入图片说明


14

扩展Dave的答案,您可以使用运行时属性在IB中设置contentMode按钮的imageView全部,而无需任何代码:

在此处输入图片说明

  • 1手段UIViewContentModeScaleAspectFit
  • 2意味着 UIViewContentModeScaleAspectFill

8

如果您只想缩小按钮图像:

yourButton.contentMode = UIViewContentModeScaleAspectFit;
yourButton.imageEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);

那应该是yourButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
sdsykes

没有尝试使用.imageView。它工作得不太好。
Tulleb


5

我有一种方法可以帮我。该方法采用UIButton并使图像外观合适。

-(void)makeImageAspectFitForButton:(UIButton*)button{
    button.imageView.contentMode=UIViewContentModeScaleAspectFit;
    button.contentHorizontalAlignment=UIControlContentHorizontalAlignmentFill;
    button.contentVerticalAlignment=UIControlContentVerticalAlignmentFill;
}

4

最干净的解决方案是使用自动布局。我降低了我的内容压缩优先级UIButton并通过Interface Builder设置了图像(不是背景图像)。之后,我添加了一些约束来定义按钮的大小(在我的情况下非常复杂),并且它就像一个魅力一样工作。


这对我有用-但只有在我选择使用“背景图片”而不是实际图片的情况下。无论如何!这让我发疯了。
安迪

在Xcode 6.2下,这对我有用,但是就像@AndrewHeinlein所说的,使用Background Image
RoLYroLLs 2015年

3

确保已将图像设置为“图像”属性,但未设置为“背景”


2

实际上,可以很容易地设置背景图像来缩放纵横比填充。只需在UIButton的子类中执行以下操作:

- (CGRect)backgroundRectForBounds:(CGRect)bounds
{
    // you'll need the original size of the image, you 
    // can save it from setBackgroundImage:forControlState
    return CGRectFitToFillRect(__original_image_frame_size__, bounds);
}

// Utility function, can be saved elsewhere
CGRect CGRectFitToFillRect( CGRect inRect, CGRect maxRect )
{
    CGFloat origRes = inRect.size.width / inRect.size.height;
    CGFloat newRes = maxRect.size.width / maxRect.size.height;

    CGRect retRect = maxRect;

    if (newRes < origRes)
    {
        retRect.size.width = inRect.size.width * maxRect.size.height / inRect.size.height;
        retRect.origin.x = roundf((maxRect.size.width - retRect.size.width) / 2);
    }
    else
    {
        retRect.size.height = inRect.size.height * maxRect.size.width / inRect.size.width;
        retRect.origin.y = roundf((maxRect.size.height - retRect.size.height) / 2);
    }

    return retRect;
}

没有子类,这不可能吗?
Iulian Onofrei

这个答案是专门针对backgroundImage的。对于主图像,可以使用imageEdgeInsets。
安迪·坡斯

我知道,我想如果没有子类就可以实现这一目标。
Iulian Onofrei

据我所知,没有子类就无法调整backgroundImage。
安迪·坡斯


0

对于Xamarin.iOS(C#):

    myButton.VerticalAlignment = UIControlContentVerticalAlignment.Fill;
    myButton.HorizontalAlignment = UIControlContentHorizontalAlignment.Fill;
    myButton.ImageView.ContentMode = UIViewContentMode.ScaleAspectFit;

-1

您只需要为三个事件设置UIButton imageview的内容模式。--

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateNormal];

[cell.button setImage:[UIImage imageWithData:data] forState:UIControlStateHighlighted];

[cell.imgIcon setImage:[UIImage imageWithData:data] forState:UIControlStateSelected];

当突出显示或选择按钮大小为SQUARE且图像大小为矩形时,我们有三个事件bcoz的代码,突出显示或选择时将显示正方形图像。

我相信它将为您工作。


您没有设置内容模式,而是在设置图像。它们不是事件,而是状态。你真是一团糟。这与问题完全无关。
manecosta 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.