如何使用Swift在iOS中刷新/重绘/重新加载UIGraphicsImageRenderer

时间:2017-09-06 15:16:24

标签: ios swift swift3 uiview

我有一个自定义UIView类,用UIGraphicsImageRenderer绘制一些线条,我有一些滑块来更改用于绘制线条的点,但这样做不会删除旧线条,它只是在它们之上绘制新的。我尝试在顶部和附近添加self.setNeedsDisplay()方法的底部,没有任何区别。

我从hackingwithswift project 27获得了如何使用UIGraphicsImageRenderer的基本思路 - 在该项目中,他使用switch语句调用不同的函数来绘制不同的东西,这似乎是清楚的&把事情改写好了。

我也试过了var clearsContextBeforeDrawing: Bool = true,但我认为我没有正确使用它,我在文档中找到了它。

我还在setNeedsDisplay文档中看到它说“你应该使用这种方法来请求只在视图的内容或外观发生变化时才重绘视图。如果只是改变视图的几何形状,视图通常不会重新绘制“ - 我正在猜测”视图的几何形状“它们意味着像转换(缩放/平移/旋转)之类的东西?

func drawLines(pointList: [CGPoint],
               cycle: Bool = false,
               lineColor: CGColor = UIColor.blue.cgColor,
               fillColor: CGColor = UIColor.clear.cgColor) {

//        self.setNeedsDisplay()
    let renderer = UIGraphicsImageRenderer(size: CGSize(width: 728, height: 984))
//        var clearsContextBeforeDrawing: Bool = true
    let img = renderer.image { ctx in
        ctx.cgContext.move(to: pointList[0])

        for v in pointList.dropFirst() {
            ctx.cgContext.addLine(to: v)
        }

        ctx.cgContext.setStrokeColor(lineColor)
        ctx.cgContext.strokePath()
    }

    let iv = UIImageView(image:img)
    iv.frame.origin = CGPoint(x: 0, y: 0)
    self.addSubview(iv)
//        self.setNeedsDisplay()
}

1 个答案:

答案 0 :(得分:1)

每次致电UIImageView时,您都会添加新的drawLines()。编写代码的方式,每个图像视图都有清晰的背景......所以你看到的是" line"彼此叠加。

您应该已将一个 UIImageView添加到self(我们将其称为theDrawingImageView),然后将您的功能更改为以:

    //let iv = UIImageView(image:img)
    //iv.frame.origin = CGPoint(x: 0, y: 0)
    //self.addSubview(iv)

    theDrawingImageView.image = img
}

编辑:这是一个完整的演示。您可以直接在游乐场页面中运行它。

它会创建一个视图控制器并添加UIButtonUIImageView。每次点击按钮时,都会生成一组12个随机点,用于在新UIImage上绘制线条,然后用于设置图像视图的.image属性。

import UIKit
import PlaygroundSupport

class TestViewController : UIViewController {


    let theDrawingImageView: UIImageView = {
        let v = UIImageView()
        v.backgroundColor = UIColor.lightGray
        v.translatesAutoresizingMaskIntoConstraints = false
        return v
    }()

    let btn: UIButton = {
        let b = UIButton()
        b.setTitle("Tap to Draw Lines", for: .normal)
        b.backgroundColor = .red
        b.translatesAutoresizingMaskIntoConstraints = false
        return b
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor(red: 0.25, green: 0.5, blue: 1.0, alpha: 1.0)

        // add button and image view to self.view
        self.view.addSubview(btn)
        self.view.addSubview(theDrawingImageView)

        // button position
        btn.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        btn.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 20.0).isActive = true

        // image view position
        theDrawingImageView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
        theDrawingImageView.topAnchor.constraint(equalTo: btn.bottomAnchor, constant: 20.0).isActive = true

        // image view width and height
        theDrawingImageView.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
        theDrawingImageView.heightAnchor.constraint(equalToConstant: 300.0).isActive = true

        // add a target for the button tap
        btn.addTarget(self, action: #selector(btnTapped(_:)), for: .touchUpInside)

    }

    // simple random number function
    func random(_ range:Range<Int>) -> Int {
        return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound - range.lowerBound)))
    }

    func btnTapped(_ sender: Any) {

        var pts = [CGPoint]()

        let maxX = Int(theDrawingImageView.bounds.size.width)
        let maxY = Int(theDrawingImageView.bounds.size.height)

        // generate a set of 12 random points
        for _ in 1...12 {
            let x = random(0..<maxX)
            let y = random(0..<maxY)
            let pt = CGPoint(x: x, y: y)
            pts.append(pt)
        }

        drawLines(imageView: theDrawingImageView, pointList: pts)

    }

    func drawLines(imageView: UIImageView,
                   pointList: [CGPoint],
                   cycle: Bool = false,
                   lineColor: CGColor = UIColor.blue.cgColor,
                   fillColor: CGColor = UIColor.clear.cgColor) {

        let renderer = UIGraphicsImageRenderer(size: imageView.bounds.size)

        // this creates a new UIImage and draws lines on it
        let img = renderer.image { ctx in

            ctx.cgContext.move(to: pointList[0])

            for v in pointList.dropFirst() {
                ctx.cgContext.addLine(to: v)
            }

            ctx.cgContext.setStrokeColor(lineColor)
            ctx.cgContext.strokePath()

        }

        // set the image view's .image to the new image with the lines drawn on it
        imageView.image = img
    }

}

let vc = TestViewController()
PlaygroundPage.current.liveView = vc