使用绘图内部旋转UIView的问题

时间:2017-01-22 11:33:28

标签: ios swift uiview rotation drawrect

我想用内部的图形(圆形,矩形或线条)旋转UIView。问题是当我旋转视图并刷新绘图时(当我更改绘图的某些属性时我需要ir,即)绘图不遵循视图...

UIView无需轮换:

UIView without rotation

旋转UIView:

UIView rotated and drawing distortion

这是我的简单代码(原始代码中的一些摘录):

主ViewController

class TestRotation: UIViewController {

// MARK: - Properties

var drawingView:DrawingView?

// MARK: - Actions

@IBAction func actionSliderRotation(_ sender: UISlider) {

    let degrees = sender.value
    let radians = CGFloat(degrees * Float.pi / 180)
    drawingView?.transform = CGAffineTransform(rotationAngle: radians)

    drawingView?.setNeedsDisplay()
}

// MARK: - Init

override func viewDidLoad() {
    super.viewDidLoad()

    drawingView = DrawingView(frame:CGRect(x:50, y:50, width: 100, height:75))

    self.view.addSubview(drawingView!)

    drawingView?.setNeedsDisplay() 
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

}

的UIView

class DrawingView: UIView {

override func draw(_ rect: CGRect) {

    let start = CGPoint(x: 0, y: 0)
    let end = CGPoint(x: self.frame.size.width, y: self.frame.size.height)

    drawCicrle(start: start, end: end)
}

func drawCicrle(start:CGPoint, end:CGPoint) {

    //Contexto
    let context = UIGraphicsGetCurrentContext()

    if context != nil {

        //Ancho
        context!.setLineWidth(2)

        //Color
        context!.setStrokeColor(UIColor.black.cgColor)
        context!.setFillColor(UIColor.orange.cgColor)

        let rect = CGRect(origin: start, size: CGSize(width: end.x-start.x, height: end.y-start.y))

        let path = UIBezierPath(ovalIn: rect)

        path.lineWidth = 2
        path.fill()
        path.stroke()

    }
}

// MARK: - Init

override init(frame: CGRect) {
    super.init(frame: frame)

    self.backgroundColor = UIColor.gray
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

}

如果我在旋转后不刷新视图,似乎暂时解决了问题,但如果由于某些其他原因(属性已更改)我必须稍后刷新,则问题会再次出现。

我该怎么办?提前致谢

1 个答案:

答案 0 :(得分:4)

当您使用frame时,您正在使用bounds

frame是包含view的矩形。它在superview view的坐标系中指定,frame在您旋转view时更改(因为旋转的方块在X中进一步延伸, Y方向比非旋转方格。)

bounds是包含view内容的矩形。它在view本身的坐标系中指定,并且在view旋转或移动时不会发生变化。

如果您在frame功能中将bounds更改为draw(_:),它将按您的预期运作:

override func draw(_ rect: CGRect) {

    let start = CGPoint(x: 0, y: 0)
    let end = CGPoint(x: self.bounds.size.width, y: self.bounds.size.height)

    drawCicrle(start: start, end: end)
}

这是一个演示,显示在滑块移动时重绘椭圆。

Rotate Oval demo

以下是更改后的代码:

class DrawingView: UIView {

    var fillColor = UIColor.orange {
        didSet {
            setNeedsDisplay()
        }
    }

    override func draw(_ rect: CGRect) {

        let start = CGPoint(x: 0, y: 0)
        let end = CGPoint(x: self.bounds.size.width, y: self.bounds.size.height)

        drawCircle(start: start, end: end)
    }

    func drawCircle(start:CGPoint, end:CGPoint) {

        //Contexto
        let context = UIGraphicsGetCurrentContext()

        if context != nil {

            //Ancho
            context!.setLineWidth(2)

            //Color
            context!.setStrokeColor(UIColor.black.cgColor)
            context!.setFillColor(fillColor.cgColor)

            let rect = CGRect(origin: start, size: CGSize(width: end.x-start.x, height: end.y-start.y))

            let path = UIBezierPath(ovalIn: rect)

            path.lineWidth = 2
            path.fill()
            path.stroke()

        }
    }

    // MARK: - Init

    override init(frame: CGRect) {
        super.init(frame: frame)

        self.backgroundColor = UIColor.gray
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

}
@IBAction func actionSliderRotation(_ sender: UISlider) {

    let degrees = sender.value
    let radians = CGFloat(degrees * Float.pi / 180)
    drawingView?.transform = CGAffineTransform(rotationAngle: radians)

    drawingView?.fillColor = UIColor(hue: CGFloat(degrees)/360.0, saturation: 1.0, brightness: 1.0, alpha: 1.0)

}