ios 在 Xcode 故事板中使用可拉伸图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11765533/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using stretchable images in Xcode storyboards
提问by Joel
I'm using storyboards to layout my view controllers and I would like to use stretchable images for my buttons (so that I don't need to generate several images with different sizes).
我正在使用故事板来布局我的视图控制器,并且我想为我的按钮使用可拉伸的图像(这样我就不需要生成多个不同大小的图像)。
Is this possible to do directly in storyboards without writing any code? I'm really liking the possibility to use storyboards for all graphic stuff and keep the code clean from UI stuff, but it seems like I can't get away with it here.
这可以在不编写任何代码的情况下直接在故事板中进行吗?我真的很喜欢将故事板用于所有图形内容并使代码与 UI 内容保持干净的可能性,但在这里我似乎无法摆脱它。
If it is not possible, what would you suggest otherwise?
如果不可能,您有什么建议?
回答by memmons
Update for iOS 7+
iOS 7+ now supports stretchable images natively via the asset catalog. Using the asset catalog you can now specify how images are sliced and how they scale (stretch or tile). These asset catalog attributes for the image will be reflected immediately in storyboard. Great new improvement. For more info, see Apple's docs on the Asset Catalog
针对 iOS 7+ 的更新
iOS 7+ 现在通过资产目录原生支持可拉伸图像。使用资产目录,您现在可以指定图像的切片方式和缩放方式(拉伸或平铺)。这些用于图像资产目录属性将立即在故事板中反映出来。伟大的新改进。有关更多信息,请参阅资产目录上的 Apple 文档
For deploying to iOS versions before 7:
It's a little known fact, but you can absolutely set cap insets of an image using only Interface Builder/Storyboard and the stretching properties in the attributes inspector. Thanks to Victorfor the original answer.
对于部署到 7 之前的 iOS 版本:
这是一个鲜为人知的事实,但是您绝对可以仅使用 Interface Builder/Storyboard 和属性检查器中的拉伸属性来设置图像的上限插入。感谢维克多的原始答案。
Looking at the stretching properties in the attributes inspector of a UIImage
, the X and Y values are the positions for the stretch starting point, relative to the entire width and height of the image. A value of 0.5 would mean a point in the middle of the image.
查看 a 的属性检查器中的拉伸属性UIImage
,X 和 Y 值是拉伸起点的位置,相对于图像的整个宽度和高度。值 0.5 表示图像中间的一个点。
The width and height are sizes for the stretchable area relative to the image size. So, setting the width to a value of 1 / imageWidth would set the stretchable area to be 1px wide.
宽度和高度是可拉伸区域相对于图像尺寸的尺寸。因此,将宽度设置为 1 / imageWidth 值会将可拉伸区域设置为 1px 宽。
Most stretchable images will stretch from the middle, so using these values for X,Y, Width, & Height will usually work:
大多数可拉伸图像将从中间拉伸,因此使用 X、Y、宽度和高度的这些值通常会起作用:
X = 0.5
Y = 0.5
Width = 1/imageWidth
Height = 1/imageHeight
Note: Unless you have a very small image you are stretching, this means that width and height properties will be very small (e.g. 0.008) and 0.0 can be used instead. So, practically speaking, 0.5, 0.5, 0.0, 0.0 will almost always work for X,Y, Width & Height.
注意:除非您要拉伸的图像非常小,否则这意味着宽度和高度属性将非常小(例如 0.008)并且可以使用 0.0 来代替。因此,实际上,0.5、0.5、0.0、0.0 几乎总是适用于 X、Y、宽度和高度。
In the small number of cases that 0.0 does not work for Width and Height this does mean you need to use a calculator to set these values in IB. However, I think that is generally preferable than having to set it programmatically as you will be able to see the resulting stretched image in IB (WYSIWYG).
在少数情况下,0.0 不适用于宽度和高度,这意味着您需要使用计算器在 IB 中设置这些值。但是,我认为这通常比必须以编程方式设置更可取,因为您将能够在 IB (WYSIWYG) 中看到生成的拉伸图像。
Update:Some people have pointed out that although stretching images works in Storyboard using the above suggestions, stretching images on buttons is still broken, even as of iOS7. Not to worry, this is easily addressed by creating a UIButton
category that takes care of setting the cap insets for control states:
更新:有些人指出,虽然使用上述建议在 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];
}
}
Using this category, you can set your stretchable image for your button via Storyboard and then easily ensure that it stretches properly by calling -setBackgroundImageStretchableForState:
in your -viewDidLoad
. Iterating through your view hierarchy makes it trivial to do this even for a large number of buttons in your view:
使用此类别,您可以通过 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];
While this isn't quite as good as having a UIButton
subclass which does this automatically for you (subclassing UIButton
isn't practical since it's a class cluster), it does give you nearly the same functionality with just a bit of boilerplate code in your viewDidLoad -- you can set all your button images in Storyboard and still get them to properly stretch.
虽然这不如拥有一个UIButton
自动为您执行此操作的子类(子类化UIButton
不切实际,因为它是一个类集群),但它确实为您提供了几乎相同的功能,只需在您的 viewDidLoad 中添加一些样板代码 - - 您可以在 Storyboard 中设置所有按钮图像,并且仍然可以正确拉伸它们。
回答by Anton Gaenko
With Xcode 6 (and iOS7+target) you can use slicing editor when working with images assets. Toggle slicing mode with Editor -> Show Slicingmenu or press Show Slicingbutton when select specific image with editor (showed below).
使用 Xcode 6(和iOS7+目标),您可以在处理图像资产时使用切片编辑器。使用编辑器切换切片模式-> 显示切片菜单或在使用编辑器选择特定图像时按显示切片按钮(如下所示)。
Then you can select image for specific display scale and drag rules or edit insets values manually.
然后您可以选择特定显示比例的图像和拖动规则或手动编辑插图值。
After that you can select this image in Interface Builder. For example I use it for UIButtonBackground Image(IB button's representation could look bad, but it should be OK when running).
之后,您可以在Interface Builder 中选择此图像。例如,我将它用于UIButton背景图像(IB 按钮的表示可能看起来很糟糕,但在运行时应该没问题)。
My buttons look well (running iOS 7.1 simulator and iOS 8 device).
我的按钮看起来不错(运行 iOS 7.1 模拟器和 iOS 8 设备)。
This Apple doc linkcould be helpful.
这个 Apple 文档链接可能会有所帮助。
回答by Lorenzo NEY
It's doable in XCode's 5.0 Interface Builder with the assets catalog. Create an image asset ( if you don't already have an asset catalog you can create one as follows:
它在带有资产目录的 XCode 5.0 Interface Builder 中是可行的。创建一个图像资产(如果您还没有资产目录,您可以按如下方式创建一个:
File
->New
->File
->Resources
->Asset Catalog
- Then
Editor
->New Image Set
- Set the images for each
Idiom
&Scale
- Then hit the
Show Slicing
button to set the slices as you wish.
File
->New
->File
->Resources
->Asset Catalog
- 然后
Editor
->New Image Set
- 为每个
Idiom
&设置图像Scale
- 然后点击
Show Slicing
按钮根据需要设置切片。
Check Apple docs here: Developer Apple: Asset Catalog HelpThen all you have to do is to set the background image of the button as the requested asset.
在此处查看 Apple 文档:Developer Apple:Asset Catalog Help然后您所要做的就是将按钮的背景图像设置为请求的资产。
EDIT: I've forgot to mention that it works as desired only in iOS7
编辑:我忘了提到它只在 iOS7 中按需要工作
回答by Philippe Sabourin
Here's what I did: I set an outlet for the button and connected it, then did this in viewDidLoad:
这是我所做的:我为按钮设置了一个插座并连接它,然后在 viewDidLoad 中执行此操作:
[self.someButton setBackgroundImage:[[self.someButton backgroundImageForState:UIControlStateNormal] resizableImageWithCapInsets:UIEdgeInsetsMake(3, 3, 4, 3)] forState:UIControlStateNormal];
This makes it so it reuses the image you set in the storyboard, so if you change it from one color to another it will work, as long as the insets dont change.
这使得它可以重用您在故事板中设置的图像,因此如果您将其从一种颜色更改为另一种颜色,只要插图不更改,它就会起作用。
For a view that had many of these things, I did this:
对于包含许多这些内容的视图,我这样做了:
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];
}
}
Note that I set the tags for all the ones I wanted stretched.
请注意,我为所有想要拉伸的标签设置了标签。
I'm in the same boat as you though, I'd love being able to set these very UI centric things on the storyboard itself.
不过,我和你在同一条船上,我很高兴能够在故事板本身上设置这些以 UI 为中心的东西。
回答by backslash112
Use the Xcode Slicing feature to specify the dimensions of a resizable center area of the image and to optionally specify end caps, which are areas of the image that should not be filled by the resizable area. See About Asset Catalogs
使用 Xcode Slicing 功能指定图像可调整大小的中心区域的尺寸,并可选择指定端盖,即不应由可调整大小的区域填充的图像区域。请参见关于资产目录