33

我正在使用故事板来布局我的视图控制器,并且我想为我的按钮使用可拉伸的图像(这样我就不需要生成多个不同大小的图像)。

这是否可以直接在情节提要中完成而无需编写任何代码?我真的很喜欢将情节提要用于所有图形内容并保持代码与 UI 内容无关的可能性,但我似乎无法摆脱它。

如果不可能,否则您会建议什么?

4

5 回答 5

75

iOS 7+ 的更新
iOS 7+ 现在通过资产目录原生支持可拉伸图像。使用资产目录,您现在可以指定图像的切片方式和缩放方式(拉伸或平铺)。图像的这些资产目录属性将立即反映在情节提要中。伟大的新改进。有关更多信息,请参阅资产目录上的 Apple 文档

部署到 7 之前的 iOS 版本:
这是一个鲜为人知的事实,但您完全可以仅使用 Interface Builder/Storyboard 和属性检查器中的拉伸属性来设置图像的 cap insets。感谢维克多的原始答案。

查看 a 的属性检查器中的拉伸属性UIImage,X 和 Y 值是拉伸起点的位置,相对于图像的整个宽度和高度。值 0.5 表示图像中间的一个点。

宽度和高度是相对于图像大小的可拉伸区域的大小。因此,将宽度设置为 1 / imageWidth 会将可拉伸区域设置为 1px 宽。

大多数可拉伸图像将从中间拉伸,因此使用 X、Y、宽度和高度的这些值通常会起作用:

X = 0.5
Y = 0.5
Width = 1/imageWidth
Height = 1/imageHeight

注意:除非您要拉伸的图像非常小,否则这意味着宽度和高度属性将非常小(例如 0.008),可以使用 0.0 代替。因此,实际上,0.5、0.5、0.0、0.0 几乎总是适用于 X、Y、宽度和高度。

在少数情况下,0.0 对宽度和高度不起作用,这确实意味着您需要使用计算器在 IB 中设置这些值。但是,我认为这通常比必须以编程方式设置它更可取,因为您将能够在 IB (WYSIWYG) 中看到生成的拉伸图像。

可拉伸图像属性

更新:有人指出,尽管使用上述建议在 Storyboard 中拉伸图像有效,但在按钮上拉伸图像仍然存在问题,即使在 iOS7 中也是如此。不用担心,这很容易通过创建一个UIButton负责为控制状态设置上限插图的类别来解决:

@implementation UIButton (Stretchable)

/* Automatically set cap insets for the background image. This assumes that
   the image is a standard slice size with a 1 px stretchable interior */
- (void)setBackgroundImageStretchableForState:(UIControlState)controlState
{
    UIImage *image = [self backgroundImageForState:controlState];
    if (image)
    {
       CGFloat capWidth =  floorf(image.size.width / 2);
       CGFloat capHeight =  floorf(image.size.height / 2);
       UIImage *capImage = [image resizableImageWithCapInsets:
                     UIEdgeInsetsMake(capHeight, capWidth, capHeight, capWidth)];

       [self setBackgroundImage:capImage forState:controlState];
    }
}

使用此类别,您可以通过 Storyboard 为按钮设置可拉伸图像,然后通过调用-setBackgroundImageStretchableForState:. -viewDidLoad即使对视图中的大量按钮,遍历视图层次结构也很容易做到这一点:

NSPredicate *predicate = 
    [NSPredicate predicateWithFormat:@"self isKindOfClass:%@",[UIButton class]];
NSArray *buttons = [self.view.subviews filteredArrayUsingPredicate:predicate];
for (UIButton *button in buttons)
   [button setBackgroundImageStretchableForState:UIControlStateNormal];

虽然这不如拥有一个UIButton自动为您执行此操作的子类(子类UIButton化不实用,因为它是一个类集群),但它确实为您提供了几乎相同的功能,只需在您的 viewDidLoad 中添加一些样板代码 - - 您可以在 Storyboard 中设置所有按钮图像,并且仍然可以正确拉伸它们。

于 2012-11-13T20:02:17.983 回答
16

使用 Xcode 6(和iOS7+目标),您可以在处理图像资源时使用切片编辑器。使用编辑器切换切片模式-> 显示切片菜单或在使用编辑器选择特定图像时按显示切片按钮(如下所示)。

显示切片按钮

然后,您可以选择特定显示比例的图像并拖动规则或手动编辑插入值。

规则

之后,您可以在Interface Builder中选择此图像。例如,我将它用于UIButton 背景图像(IB 按钮的表示可能看起来很糟糕,但运行时应该没问题)。

我的按钮看起来不错(运行 iOS 7.1 模拟器和 iOS 8 设备)。

在此处输入图像描述

这个 Apple 文档链接可能会有所帮助。

于 2015-03-02T08:32:28.727 回答
11

它在 XCode 的 5.0 Interface Builder 中与资产目录是可行的。创建一个图像资产(如果您还没有资产目录,您可以按如下方式创建一个:

  1. File-> New-> File-> Resources->Asset Catalog
  2. 然后Editor->New Image Set
  3. 为每个Idiom&设置图像Scale
  4. 然后点击Show Slicing按钮以根据需要设置切片。

在此处查看 Apple 文档:Developer Apple: Asset Catalog Help 然后您所要做的就是将按钮的背景图像设置为请求的资产。

编辑:我忘了提到它只在 iOS7 中按要求工作

于 2013-10-06T04:40:44.433 回答
2

这是我所做的:我为按钮设置了一个插座并连接它,然后在 viewDidLoad 中执行此操作:

[self.someButton setBackgroundImage:[[self.someButton backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];

这使它可以重用您在情节提要中设置的图像,因此如果您将其从一种颜色更改为另一种颜色,只要插图不改变,它就会起作用。

对于包含许多此类内容的视图,我这样做了:

for (UIView * subview in self.view.subviews) {
        if ([subview isKindOfClass:[UIImageView class]] && subview.tag == 10) {
            UIImageView* textFieldImageBackground = (UIImageView*)subview;
            textFieldImageBackground.image = [textFieldImageBackground.image stretchableImageWithLeftCapWidth:7 topCapHeight:5];
        } else if([subview isKindOfClass:[UIButton  class]] && subview.tag == 11) {
            UIButton * button = (UIButton*)subview;
            [button setBackgroundImage:[[button backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];
        }
    }

请注意,我为所有我想要拉伸的标签设置了标签。

不过,我和你在同一条船上,我希望能够在情节提要本身上设置这些以 UI 为中心的东西。

于 2012-08-07T17:41:09.827 回答
0

使用 Xcode Slicing 功能来指定图像可调整大小的中心区域的尺寸,并可选择指定端盖,即不应由可调整大小的区域填充的图像区域。请参阅关于资产目录

于 2015-02-07T04:56:10.283 回答