如何将内容模式为 scaleAspectFill 的图像底部像素拉伸到全屏 iOS?

How to stretch the bottom pixels of image to full screen that the content mode is scaleAspectFill on iOS?

我想将内容模式为 scaleAspectFill 的图像设置为背景,并将线条的底部像素拉伸为全屏。

这是一个简单的示例图片,尺寸为 1280x300px,将在 Assets 中设置为 2x。

这是故事板的屏幕截图。我想将线条的底部像素填充为白色 space。

StretchingSlicing功能我都试过了,但是效果都不是我想要的。

这是我在 iPhone 4S 上想要的预期结果。

尝试使用 (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingModeresizingModel.stretch

如果要文字停靠在顶部,蓝色竖线在底部,我们试试这个(假设蓝线高度为20px,即图片顶部到文字底部的距离'Before you go' 为 100 px)

let image = yourOriginalImage.resizableImage(withCapInsets: UIEdgeInsets(top: 100, left: 10, bottom: 10, right: 10), resizingMode: .stretch)

希望对您有所帮助。

更新

上面的代码行显示如下

不清楚您是如何调整图像大小的...

您发布的 1280 x 300 图片,其中 imageView 限制为视图的宽度...

AspectFit:

AspectFill(使用图像的原始 300 高度):

AspectFill(使用 150 高度):

但是,假设图像中的文本长度不同,您可能会得到...

AspectFit:

AspectFill(使用 150 高度):

但是...假设您有解决该问题的计划,一种方法是使用两个图像视图。

顶部图像视图将保留您已有的完整图像...使用 .scaleAspectFill 并限制其高度以仅显示图像中居中的文本。

底部图像视图将被限制在视图的底部,.scaleToFill,您可以使用此扩展:

extension UIImage {

    // return the CGRect portion as a new UIImage
    func subImage(in rect: CGRect) -> UIImage? {
        let scale = UIScreen.main.scale
        guard let cgImage = cgImage else { return nil }
        guard let crop = cgImage.cropping(to: rect) else { return nil }
        return UIImage(cgImage: crop, scale: scale, orientation:.up)
    }

}

// then, use it like this
let bottomImage = fullImage.subImage(in: CGRect(x: 0.0, y: fullImage.size.height - 1.0, width: 8.0, height: 1.0))

获取原始图像的 8px x 1px 部分。将底部图像视图的 .image 设置为该图像,它将缩放以填充整个框架。

结果:

这是一个完整的示例,使用您的原始图像(我将其命名为 "wake.png"):

extension UIImage {

    // return the CGRect portion as a new UIImage
    func subImage(in rect: CGRect) -> UIImage? {
        let scale = UIScreen.main.scale
        guard let cgImage = cgImage else { return nil }
        guard let crop = cgImage.cropping(to: rect) else { return nil }
        return UIImage(cgImage: crop, scale: scale, orientation:.up)
    }

}

class StretchBottomViewController: UIViewController {

    var topImageView: UIImageView = {
        let v = UIImageView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.contentMode = .scaleAspectFill
        v.setContentHuggingPriority(.required, for: .vertical)
        return v
    }()

    var bottomImageView: UIImageView = {
        let v = UIImageView()
        v.translatesAutoresizingMaskIntoConstraints = false
        v.contentMode = .scaleToFill
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(topImageView)
        view.addSubview(bottomImageView)

        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            // constrain top image view to top / leading / trailing at Zero
            topImageView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            topImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            topImageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),

            // constrain bottom image view to bottom of top image view / leading / trailing at Zero
            bottomImageView.topAnchor.constraint(equalTo: topImageView.bottomAnchor, constant: 0.0),
            bottomImageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            bottomImageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),

            // constrain bottom image view to bottom at Zero
            bottomImageView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),

            // however you are determining the height of the top image view
            // using 150 here to work with your original image
            topImageView.heightAnchor.constraint(equalToConstant: 150.0),

        ])

        // load "wake me up" image
        if let fullImage = UIImage(named: "wake") {
            // get the bottom part of the full image (8 pixels wide, 1-pixel tall)
            if let bottomImage = fullImage.subImage(in: CGRect(x: 0.0, y: fullImage.size.height - 1.0, width: 8.0, height: 1.0)) {
                topImageView.image = fullImage
                bottomImageView.image = bottomImage
            }
        }

    }

}