【问题标题】:A simple way to put a UIImage in a UIButton将 UIImage 放入 UIButton 的简单方法
【发布时间】:2011-05-28 23:17:54
【问题描述】:

我的 iPhone 应用中有一个 UIButton。我将其大小设置为 100x100。

我希望在按钮中显示一个 400x200 的图像。

按钮仍然需要保持在 100x100...我希望图像缩小以适应...但是 保持正确的纵横比。

我认为这就是“Aspect Fit”的用途。

我是否将我的图像包含在 setImage 或 setBackgroundImage 中?

我是否为按钮设置 AspectFit?还是图像?还是背景图片?

(我需要较小的图像增大尺寸。而较大的图像应该减小尺寸。 始终将按钮保持在 100x100。)

我已经尝试了以上所有方法的无数组合......但我似乎无法得到 一切都在同一时间工作:

  • 不要将按钮的大小更改为 100x100。
  • 不要破坏图片的纵横比。
  • 始终增大小图像以适应按钮。
  • 始终缩小大图像以适应按钮。
  • 切勿剪裁任何图像边缘。
  • 永远不需要“将 UIButtons 置于所有 UIimage 之上”的技巧。
  • 不要要求每个人都升级到 v4.2.1 只是为了使用新的框架方法。

我看到这么多应用程序,有这么多功能齐全的图像按钮......我简直不敢相信我无法弄清楚这个非常简单、非常常见的事情。

呃。

【问题讨论】:

    标签: iphone image uiimageview uibutton aspect-ratio


    【解决方案1】:

    UIButton 坏了。这是简短的答案。其 image 和 backgroundImage 属性中的 UIImageViews 不尊重 UIViewContentMode 设置。它们是只读属性,虽然这些 UIImageViews 的UIImage 内容可以通过setImage:setBackgroundImage: 方法设置,但内容模式不能。

    解决方案是在你的包中提供适当大小的图像,或者放下 UIImageView,按照你想要的方式配置它,然后在它上面放置一个清晰的“自定义”UIButton。我保证,这就是你见过的所有花哨的专业应用程序所使用的技巧。我们都必须这样做。

    【讨论】:

    • 图片不在我的捆绑包中...它们是稍后将加载的人们的图片。所以所有现有的按钮功能都不允许这个简单的事情????按钮的图像是无用的。按钮的背景图像是无用的。所有各种适合方面的选择都是无用的。 (苹果为什么要把它们放进去……如果它们连“让这个图像适合这个按钮”这样简单的事情都做不了?)
    • 有谁知道这个“烦恼”是否已在更高版本的 xcode 中得到解决?
    • 从 iOS 6.1.3 开始,他们仍然不尊重这个属性。
    【解决方案2】:
    UIImage *img = [UIImage imageNamed:@"yourImageName"];
    button.imageView.contentMode = UIViewContentModeScaleAspectFit;
    [button setImage:img forState:UIControlStateNormal];
    

    【讨论】:

    • 感谢此次更新。对于读到这么远的所有其他人:是的!实际上,Apple 似乎已经解决了 UIButton 的纵横比问题。上面答案的几行可以跳过上面的“解决方法”。
    【解决方案3】:

    要正确执行此操作,我实际上会以编程方式调整图像大小和操作图像以获得所需的纵横比。这避免了对任何视图层次结构的修改,也减少了对单个操作的任何性能影响,而不是每次重绘。

    这个(未经测试的)代码应该有助于说明我的意思:

    CGSize imageSize = image.size;
    CGFloat currentAspect = imageSize.width / imageSize.height;
    
    // for purposes of illustration
    CGFloat targetWidth = 100;
    CGFloat targetHeight = 100;
    CGFloat targetAspect = targetWidth / targetHeight;
    
    CGFloat newWidth, newHeight;
    
    if (currentAspect > targetAspect) {
        // width will end up at 100, height needs to be smaller
        newWidth = targetWidth;
        newHeight = targetWidth / currentAspect;
    } else {
        // height will end up at 100, width needs to be smaller
        newHeight = targetHeight;
        newWidth = targetHeight * currentAspect;
    }
    
    size_t bytesPerPixel = 4;
    
    // although the image will be resized to { newWidth, newHeight }, it needs
    // to be padded with empty space to provide the aspect fit behavior
    //
    // use calloc() to clear the data as it's allocated
    void *imageData = calloc(targetWidth * targetHeight, bytesPerPixel);
    
    if (!imageData) {
        // error out
        return;
    }
    
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    if (!colorSpace) {
        // error out
        return;
    }
    
    CGContextRef context = CGBitmapContextCreate(
        imageData,
        targetWidth,
        targetHeight,
        8, // bits per component
        targetWidth * bytesPerPixel, // bytes per row
        colorSpace,
        kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst
    );
    
    CGColorSpaceRelease(colorSpace);
    
    // now we have a context to draw the original image into
    // in doing so, we want to center it, so prepare the geometry
    CGRect drawRect = CGRectMake(
        floor((targetWidth - newWidth) / 2),
        floor((targetHeight - newHeight) / 2),
        round(newWidth),
        round(newHeight)
    );
    
    CGContextDrawImage(context, drawRect, image.CGImage);
    
    // now that the bitmap context contains the aspect fit image with transparency
    // letterboxing, we want to pull out a new image from it
    CGImageRef newImage = CGBitmapContextCreateImage(context);
    
    // destroy the temporary context
    CGContextRelease(context);
    free(imageData);
    
    // and, finally, create a new UIImage
    UIImage *newUIImage = [UIImage imageWithCGImage:newImage];
    CGImageRelease(newImage);
    

    如果其中任何部分不清楚,请告诉我。

    【讨论】:

    • 哇。我也会试试的。但是这个简单的东西真的是THAT一大堆代码吗?使此图像适合此按钮。 “设置按钮大小”和“设置宽高比”和“设置此图像”类型的东西真的永远无法完成吗?
    • @Alice 好吧,这段代码的 sn-p 与您设置其中一种内容模式时在后台执行的操作非常相似。在我的项目中,我通常使用隐藏在一些易于访问的全局函数或方法(如UIImage 上的类别)后面的代码,然后我需要做的任何手动缩放都是轻而易举的事。
    • @justin Spahr-Summers,谢谢它真的对我有用。但我的问题是它可以处理任何大小的图像吗?我问的是对高清图像和缩略图的感知。
    【解决方案4】:

    因为我的尝试都没有奏效......

    也许我应该问这个。使用 UIButton 时:

    DO 我使用 setImage 而不是 setBackgroundImage? (为什么两者都有?)

    什么时候我使用“Aspect Fit”而不是“Center”? (当我期望它们分别“保持纵横比”和“不调整任何大小”时,为什么它们似乎都在拉伸我的图像。)

    还有一个大问题:为什么这么普遍的事情……这么大的一团糟?

    如果我能找到一种解决方法,例如:只需使用 UIImage 并检测 TAPS,一切都会得到解决。 (但这似乎是一场更大的代码噩梦。)

    Apple,如果你试图让我的工作变得更轻松......你反而让它变得更加混乱 400 倍。

    【讨论】:

      【解决方案5】:

      我认为 Dan 想说的(但从未说过)就是这样做:

      • 使用“临时图像”为您调整大小。
      • 临时图像需要设置为 ASPECT FIT 和 HIDDEN。
      • 确保您的按钮设置为您想要的大小,而不是设置为 ASPECT FIT。
      // 制作与按钮大小相同的框架 CGRect aFrame = CGRectMake(0, 0, myButton.frame.size.width, myButton.frame.size.height); // 将临时图像设置为按钮的大小 imgTemp.frame = aFrame; // 将你的图像放入临时图像 imgTemp.image = anImage; // 将调整大小的临时图像复制到您的按钮 [myButton setBackgroundImage:tempImage forState:UIControlStateNormal];

      【讨论】:

      • 我刚试过。临时图像出来 PERFECT。但是无法将该图像(及其新尺寸)复制到我的按钮中。如果我使用setBackgroundImage,图像被拉伸,纵横比被破坏。
      • > 确保您的按钮未设置为 ASPECT FIT....................... ...... 如何????您不能将其设置为“无”。我认为“非拉伸”选择是“中心”,但无论如何都会拉伸它。呃。
      【解决方案6】:

      在按钮上放置一个图像视图,将图像设置为图像视图而不是按钮。

      一切顺利。

      【讨论】:

      • 实际上,我会将UIImageView 置于按钮下方,并将按钮设为“自定义”,使其不可见。
      • 我想“正确”地做到这一点,并避免 25 个按钮的 hack……超过 25 张图像……必须创建 50 个对象以及所有内存、维护、插座、操作等。所有强大的内置按钮方法有什么用...如果每个人的解决方案都是“不要使用它们”???
      【解决方案7】:

      我会将图像大小调整为 100x100,同时保持图像中包含的内容的纵横比。然后将 UIButton 的 backgroundImage 属性设置为图片。

      【讨论】:

      • 这正是我需要做的......但是如何? (当某人的“答案”是“就去做”时,你不喜欢它吗?而不是 HOW 去做吗?)我如何调整图像的大小?如何保持它的纵横比? (请记住,我不想将图像大小调整为 100x100...我希望它 FIT 在 100x100 内(无论其原始大小或新大小)...只要它的宽度(或高度)正好为 100。
      • 调整图片大小的方法有很多种,比如stackoverflow.com/questions/2658738/…你有没有试过简单地创建一个UIImageView作为按钮的子视图?我不确定它是否会起作用,但如果它起作用的话,这似乎是最简单的方法。
      • 我不能使用合法的、无证的东西。而且我不能强迫每个人都更新使用 v4.2.1 框架。
      • @Dan - 问题是,UIButton 将始终“缩放以填充”背景图像。请参阅上面丹·雷的回答。您是否尝试过您提出的答案?
      【解决方案8】:

      几天前我遇到了同样的问题并解决了。请试试这个

      [_profilePicBtn setImage:profilePic forState:UIControlStateNormal];
      _profilePicBtn.imageView.contentMode = UIViewContentModeScaleAspectFit;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-09
        • 1970-01-01
        • 1970-01-01
        • 2011-05-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多