Swift 3 以编程方式绘制 uiimage

Swift 3 draw uiimage programmatically

我没有 Core Graphics 方面的经验,但我需要绘制如下所示的动态 uiimage:

left

whole

(其实我是想让灰色的区域清晰一些,这样红色看起来会像飘浮的)

这是我试过的代码:

public extension UIImage {

    public convenience init?(color: UIColor, size: CGSize = CGSize(width: 27, height: 5), isWhole: Bool = true) {
        let totalHeight: CGFloat = 5.0
        let topRectHeight: CGFloat = 1.0

        //if (isWhole) {
        let topRect = CGRect(origin: .zero, size: CGSize(width: size.width, height: topRectHeight))
        UIGraphicsBeginImageContextWithOptions(topRect.size, false, 0.0)
        color.setFill()
        UIRectFill(topRect)

        let bottomRect = CGRect(origin: CGPoint(x: 0, y: topRectHeight), size: CGSize(width: size.width, height: totalHeight - topRectHeight))
        UIGraphicsBeginImageContextWithOptions(bottomRect.size, false, 0.0)
        UIColor.blue.setFill()
        UIRectFill(bottomRect)

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        guard let cgImage = image?.cgImage else { return nil }
        self.init(cgImage: cgImage)
    }

我建议在您创建的第一个上下文中创建两条路径,即

let topPath = UIBezierPath(rect: topRect)
color.setFill()
topPath.fill()

let bottomPath = UIBezierPath(rect: bottomRect)
UIColor.blue.setFill()
bottomPath.fill()

然后就可以从当前上下文中获取图像了。

这是一个示例,如果将 isWhole 属性 设置为 false,则可以得到第一张图像,如果将其设置为 true,则可以得到第二张图像。您可以将此代码粘贴到 viewDidLoad 中进行测试和使用。

    var isWhole = false
    UIGraphicsBeginImageContextWithOptions(CGSize.init(width: 27, height: 5), false,0.0)
    var context = UIGraphicsGetCurrentContext()
    context?.setFillColor(UIColor.red.cgColor)
    if(context != nil){
        if(isWhole){
            context?.fill(CGRect(x: 0, y: 0, width: 27, height: 2.5))
        }
        else{
            context?.fill(CGRect(x: 0, y: 0, width: 13.5, height: 2.5))
        }
        context?.setFillColor(UIColor.gray.cgColor)
        context?.fill(CGRect(x: 0, y: 2.5, width: 27, height: 2.5))
    }


    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    var imageView = UIImageView(frame: CGRect(x: 100, y: 200, width: 27, height: 5))
    imageView.image = newImage
    self.view.addSubview(imageView)
    UIGraphicsEndImageContext()

如果你需要你的红色矩形是圆角的,只需将 fill(rect:CGRect) 更改为如下路径:

    if(isWhole){
        context?.addPath(CGPath(roundedRect: CGRect(x: 0, y: 0, width: 27, height: 2.5), cornerWidth: 1, cornerHeight: 1, transform: nil))
        context?.fillPath()
    }

我知道您在评论中说过您不能使用 UIViews,但是您想要的 "looks" 可以通过视图轻松完成。为什么不那个,然后简单地把它变成UIImage?

override func viewDidLoad() {
    super.viewDidLoad()

    let imageContainer = UIView(frame: CGRect(x: 30, y: 40, width: 110, height: 60))
    imageContainer.backgroundColor = view.backgroundColor
    view.addSubview(imageContainer)

    let redView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
    redView.backgroundColor = UIColor.red
    let grayView = UIView(frame: CGRect(x: 10, y: 30, width: 100, height: 30))
    grayView.backgroundColor = UIColor.gray
    imageContainer.addSubview(redView)
    imageContainer.addSubview(grayView)

    let imageView = UIImageView(frame: CGRect(x: 100, y: 140, width: 200, height: 200))
    imageView.contentMode = .scaleAspectFit
    imageView.image = createImage(imageContainer)

    view.addSubview(imageView)
}

func createImage(_ view: UIView) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(
        CGSize(width: view.frame.width, height: view.frame.height), true, 1)
    view.layer.render(in: UIGraphicsGetCurrentContext()!)
    let image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return image!
}