2017-01-22 10 views
2

Я хочу повернуть UIView с рисунком внутри (круг, прямоугольник или линия). Проблема заключается в том, когда я повернуть изображение и обновить чертеж (мне нужна ИК, когда я изменить некоторые свойства чертежа, то есть) рисунок не следовать виду ...Проблемы с вращением UIView с чертежом внутри

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) 
} 

} 

Кажется, что проблема решена во время, если я не обновить вид после поворота , но если мне нужно обновить позже по какой-то другой причине (свойства изменены), проблема снова появится.

Что я могу сделать? Заранее спасибо

ответ

3

Вы используете frame, когда вы должны использовать bounds.

frame - это прямоугольник, который содержит view. Он задается в системе координат superviewview, а 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) 

} 
+0

Спасибо! Я видел ваш ответ после многого, и, прежде чем я увидел его, я обнаружил проблему о прямых vs-границах ...;) –