xcode 在 swift 中以编程方式为 iOS 设置图像的拉伸参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/35607634/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 08:34:51  来源:igfitidea点击:

Set stretching parameters for images programmatically in swift for iOS

iosxcodeswift

提问by Milad.Nozari

So if we want to stretch only parts of an image, be it a regular image or a background image, we use the following settings in layout editor:

因此,如果我们只想拉伸图像的一部分,无论是常规图像还是背景图像,我们在布局编辑器中使用以下设置:

enter image description here

在此处输入图片说明

How do you set those programmatically?

你如何以编程方式设置这些?

I'm using Xcode 7.2.1

我正在使用 Xcode 7.2.1

回答by dfri

Specifying the cap insets of your image

指定图像的大写插图

You can set the stretch specifics by making use of the UIImagemethod .resizableImageWithCapInsets(_:UIEdgeInsets, resizingMode: UIImageResizingMode).

您可以使用UIImage方法设置拉伸细节.resizableImageWithCapInsets(_:UIEdgeInsets, resizingMode: UIImageResizingMode)

Declaration

func resizableImageWithCapInsets(capInsets: UIEdgeInsets, resizingMode: UIImageResizingMode) -> UIImage

Description

Creates and returns a new image object with the specified cap insets and options.

A new image object with the specified cap insets and resizing mode.

Parameters

capInsets: The values to use for the cap insets.

resizingMode: The mode with which the interior of the image is resized.

宣言

func resizableImageWithCapInsets(capInsets: UIEdgeInsets, resizingMode: UIImageResizingMode) -> UIImage

描述

创建并返回一个具有指定上限插入和选项的新图像对象。

具有指定的帽插入和调整大小模式的新图像对象。

参数

capInsets:用于大写插图的值。

resizingMode:调整图像内部大小的模式。



Example: custom stretching using the specified cap insets

示例:使用指定的帽插入自定义拉伸

As an example, let's try to---programmatically---stretch my (current) profile picture along its width, precisely at my right leg (left side from viewing point of view), and leave the rest of the image with its original proportions. This could be comparable to stretching the width of some button texture to the size of its content.

举个例子,让我们尝试---以编程方式---沿着它的宽度拉伸我的(当前)个人资料图片,精确地在我的右腿(从视角来看左侧),并将图像的其余部分保留为原始图片比例。这类似于将某些按钮纹理的宽度拉伸到其内容的大小。

First, let's load our original image foo.pngas an UIImageobject:

首先,让我们将原始图像foo.png作为UIImage对象加载:

let foo = UIImage(named: "foo.png") // 328 x 328

enter image description here

在此处输入图片说明

Now, using .resizableImageWithCapInsets(_:UIEdgeInsets, resizingMode: UIImageResizingMode), we'll define another UIImageinstance, with specified cap insets (to the middle of my right leg), and set resizing mode to .Stretch:

现在,使用.resizableImageWithCapInsets(_:UIEdgeInsets, resizingMode: UIImageResizingMode),我们将定义另一个UIImage实例,具有指定的帽插入(到我的右腿中间),并将调整大小模式设置为.Stretch

/* middle of right leg at ~ |-> 0.48: LEG :0.52 <-| along 
   image width (for width normalized to 1.0)                */
let fooWidth = foo?.size.width ?? 0
let leftCapInset = 0.48*fooWidth
let rightCapInset = fooWidth-leftCapInset // = 0.52*fooWidth

let bar = UIEdgeInsets(top: 0, left: leftCapInset, bottom: 0, right: rightCapInset)
let fooWithInsets = foo?.resizableImageWithCapInsets(bar, resizingMode: .Stretch) ?? UIImage()

Note that 0.48literal above corresponds to the value you enter for Xin the interface builder, as shown in the image in your question above (or as described in detail in the link provided by matt).

请注意,0.48上面的文字对应于您X在界面构建器中输入的值,如上面问题中的图像所示(或在 matt 提供的链接中详细描述)。

Moving on, we finally place the image with cap insets in an UIImageView, and let the width of this image view be larger than the width of the image

继续,我们最终将带有大写插图的图像放入 an 中UIImageView,并让此图像视图的宽度大于图像的宽度

/* put 'fooWithInsets' in an imageView.
   as per default, frame will cover 'foo.png' size */
let imageView = UIImageView(image: fooWithInsets)

/* expand frame width, 328 -> 600 */
imageView.frame = CGRect(x: 0, y: 0, width: 600, height: 328)

The resulting view stretches the original image as specified, yielding an unproportionally long leg.

结果视图按指定拉伸原始图像,产生不成比例的长腿。

enter image description here

在此处输入图片说明

Now, as long as the frame of the image has 1:1width:heightproportions (328:328), stretching will be uniform, as if only fitting any image to a smaller/larger frame. For any frame with widthvalues larger than the height(a:1, ratio, a>1), the leg will begin to stretch unproportionally.

现在,只要图像的框架具有1:1width:height比例 ( 328:328),拉伸就会均匀,就好像只将任何图像适合较小/较大的框架一样。对于width值大于height( a:1, ratio, a>1) 的任何帧,腿将开始不成比例地拉伸。



Extension to match the X, width, Yand heightstretching properties in the Interface Builder

扩展匹配XwidthYheight在Interface Builder的拉伸性能

Finally, to thoroughly actually answer your question (which we've really only done implicitly above), we can make use of the detailed explanation of the X, width, Yand heightInterface Builder stretching properties in the link provided by matt, to construct our own UIImageextension using (apparently) the same properties, translated to cap insets in the extension:

最后,要彻底居然回答你的问题(这我们真的只是含蓄地做以上),我们可以利用的详细说明XwidthYheightInterface Builder的拉伸性能由Matt提供的链接,来构建我们自己的UIImage使用扩展(显然)相同的属性,转换为扩展中的上限插图:

extension UIImage {
    func resizableImageWithStretchingProperties(
    X X: CGFloat, width widthProportion: CGFloat,
    Y: CGFloat, height heightProportion: CGFloat) -> UIImage {

        let selfWidth = self.size.width
        let selfHeight = self.size.height

        // insets along width
        let leftCapInset = X*selfWidth*(1-widthProportion)
        let rightCapInset = (1-X)*selfWidth*(1-widthProportion)

        // insets along height
        let topCapInset = Y*selfHeight*(1-heightProportion)
        let bottomCapInset = (1-Y)*selfHeight*(1-heightProportion)

        return self.resizableImageWithCapInsets(
            UIEdgeInsets(top: topCapInset, left: leftCapInset,
                bottom: bottomCapInset, right: rightCapInset),
            resizingMode: .Stretch)
    }
}

Using this extension, we can achieve the same horizontal stretching of foo.pngas above, as follows:

使用这个扩展,我们可以实现foo.png和上面一样的水平拉伸,如下:

let foo = UIImage(named: "foo.png") // 328 x 328
let fooWithInsets = foo?.resizableImageWithStretchingProperties(
    X: 0.48, width: 0, Y: 0, height: 0) ?? UIImage()

let imageView = UIImageView(image: fooWithInsets)
imageView.frame = CGRect(x: 0, y: 0, width: 600, height: 328)


Extending our example: stretching width as well as height

扩展我们的示例:拉伸宽度和高度

Now, say we want to stretch my right leg as above (along width), but in addition also my hands and left leg along the height of the image. We control this by using the Yproperty in the extension above:

现在,假设我们想像上面一样拉伸我的右腿(沿宽度),但另外还要沿图像的高度拉伸我的手和左腿。我们通过使用Y上面扩展中的属性来控制它:

let foo = UIImage(named: "foo.png") // 328 x 328
let fooWithInsets = foo?.resizableImageWithStretchingProperties(
    X: 0.48, width: 0, Y: 0.45, height: 0) ?? UIImage()

let imageView = UIImageView(image: fooWithInsets)
imageView.frame = CGRect(x: 0, y: 0, width: 500, height: 500)

Yielding the following stretched image:

产生以下拉伸图像:

enter image description here

在此处输入图片说明



The extension obviously allows for a more versatile use of the cap inset stretching (comparable versatility as using the Interface Builder), but note that the extension, in its current form, does not include any user input validation, so it's up to the caller to use arguments in the correct ranges.

该扩展显然允许更广泛地使用大写插入拉伸(与使用界面生成器具有相当的多功能性),但请注意,当前形式的扩展不包括任何用户输入验证,因此由调用者决定在正确的范围内使用参数。

Finally, a relevant note for any operations covering images and their coordinates:

最后,对涉及图像及其坐标的任何操作的相关说明:

Note:Image coordinate axes x(width) and y(height) run as

x (width):  left to right (as expected)
y (height): top to bottom (don't miss this!)

注意:图像坐标轴x(宽度)和y(高度)运行为

x (width):  left to right (as expected)
y (height): top to bottom (don't miss this!)