【问题标题】:scale Image in an UIButton to AspectFit?将 UIButton 中的图像缩放到 AspectFit?
【发布时间】:2011-01-02 18:38:55
【问题描述】:

我想将图像添加到 UIButton,并且还想缩放我的图像以适应 UIButton(使图像更小)。请教我怎么做。

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

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

【问题讨论】:

标签: ios objective-c cocoa-touch uibutton uikit


【解决方案1】:

我遇到了同样的问题。只需设置 UIButton 内 ImageView 的 ContentMode。

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

希望这会有所帮助。

【讨论】:

  • 确保您正在设置 imageView。我也有一段时间没有注意到我仍在使用 backgroundImageView 并且它不起作用。
  • 当按钮状态为“高亮”时,此方法似乎有些问题。图像将返回填充模式。有什么想法吗?
  • 这对我不起作用。但是,我通过使用 [self.itemImageButton setbackgroundImage:[UIImage imageNamed:stretchImage] forState:UIControlStateNormal]; 使它工作
  • 这对我有用。我如上所述设置内容模式。但是,您还需要设置相同的图像高亮状态,以避免图像回到“填充模式”。例如 [imageButton setImage:image forState:UIControlStateHighlighted];
  • 您可以在 Interface Builder 中使用键路径 imageView.contentMode、键入 Number 和值 1 来执行此操作
【解决方案2】:

这里没有一个答案真的对我有用,我用下面的代码解决了这个问题:

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

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

【讨论】:

  • 这不会为您提供 OP 要求的 aspect fit 行为。
  • @OrtwinGentz 您可以选择模式并设置Aspect fit 而不是scale to fill
【解决方案3】:

aspect fit 模式下以编程方式设置 UIButton imageView 的最简单方法:

斯威夫特

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

Objective-C

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

注意: 您可以将 .scaleAspectFit (UIViewContentModeScaleAspectFit) 更改为 .scaleAspectFill (UIViewContentModeScaleAspectFill) 以设置 aspect fill 模式

【讨论】:

    【解决方案4】:

    如果您真的想缩放图像,请执行此操作,但您应该在使用之前调整它的大小。在运行时调整它的大小只会丢失 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 加载的,所以我无法在编译时调整它的大小。顺便说一句,非常感谢您的回复。
    • 因为图像被放置在 CALayer 中,由 Quartz 渲染和缓存,如果将其以全尺寸放置在其中,性能应该不会更差。无论哪种方式,您都在调整 ~1 次。如果您不断调整按钮的大小或执行其他会触发 Quartz 重绘图像层的操作,gcamp 的答案会更加重要。
    • 图像质量似乎下降了。我在 iphone 6 plus 上进行测试。这是真的吗?我也有 3x 图像。
    • 是的,这段代码已经很老了。它是 UIGraphicsBeginImageContext 而不是 UIGraphicsBeginImageContextWithOptions。刚刚修好了。
    • 是的,但在很多情况下,如果你松开几个周期也没关系,所以填满内存没有意义
    【解决方案5】:

    我遇到了图像没有按比例调整大小的问题,所以我修复它的方法是使用边缘插图。

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

    【讨论】:

      【解决方案6】:

      这现在可以通过 IB 的 UIButton 属性来完成。关键是把你的图片设置为背景,否则就不行了。

      【讨论】:

        【解决方案7】:

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

        • 1 表示UIViewContentModeScaleAspectFit
        • 2 意味着 UIViewContentModeScaleAspectFill

        【讨论】:

          【解决方案8】:

          1 - 清除按钮默认文本(重要)

          2 - 像图像一样设置对齐方式

          3 - 像图片一样设置内容模式

          【讨论】:

          • 很好的答案兄弟..帮助了我很多。谢谢!
          【解决方案9】:

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

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

          【讨论】:

          • 那应该是 yourButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
          • 没有尝试使用 .imageView。它工作得很好。
          【解决方案10】:

          我有一个方法可以为我做这件事。 该方法采用UIButton 并使图像方面适合。

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

          【讨论】:

            【解决方案11】:

            最干净的解决方案是使用自动布局。我降低了UIButtonContent Compression Resistance Priority,并通过Interface Builder 设置了图像(不是背景图像)。之后,我添加了一些约束来定义按钮的大小(在我的情况下非常复杂),它就像一个魅力。

            【讨论】:

            • 这对我有用——但前提是我选择使用“背景图像”,而不是实际图像。什么都行!这让我发疯了。
            • 在 Xcode 6.2 下这对我有用,但就像@AndrewHeinlein 所说,使用了Background Image
            【解决方案12】:

            确保您已将图像设置为图像属性,而不是背景

            【讨论】:

              【解决方案13】:

              斯威夫特 5.0

               myButton2.contentMode = .scaleAspectFit
               myButton2.contentHorizontalAlignment = .fill
               myButton2.contentVerticalAlignment = .fill
              

              【讨论】:

                【解决方案14】:

                背景图片实际上可以很容易地设置为比例填充。只需要在 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;
                }
                

                【讨论】:

                • 没有子类就不能这样吗?
                • 这个答案专门针对 backgroundImage。对于主图像,您可以使用 imageEdgeInsets。
                • 我知道,我想知道是否可以在没有子类的情况下实现这一目标。
                • 据我所知,没有子类化是无法调整 backgroundImage 的。
                【解决方案15】:

                对于 Xamarin.iOS (C#):

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

                【讨论】:

                  【解决方案16】:

                  您只需要为三个事件设置 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];
                  

                  我们有三个事件 bcoz 的代码,同时突出显示或选择如果按钮大小为 SQUARE 并且图像大小为矩形,那么它将在突出显示或选择时显示方形图像。

                  我相信它对你有用。

                  【讨论】:

                  • 您不是在设置内容模式,而是在设置图像。它们不是事件,它们是状态。你把事情搞得一团糟。这与问题完全无关。
                  猜你喜欢
                  • 2020-06-14
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-09-08
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多