6 jun
2017

Retrieving the right position of a scaled UIView

I'm having trouble retrieving the current position of a view, absolutely in the iPhone screen, when the view is scaled. Here is a minimal example of what I've done.

I have a single elliptical view on screen. When I tap, it grows and start to shiver to show that it is selected. Then I can drag the view all over the screen.

Here is the code:

ViewController

import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // The View
    let toDrag = MyView(frame: CGRect(x: 0, y: 0, width: 50, height: 40))
    toDrag.center = CGPoint(x:100, y:100)
    // The gesture recognizer
    let panGestRec = UIPanGestureRecognizer(target: self, action:#selector(self.panView(sender:)))
    toDrag.addGestureRecognizer(panGestRec)

    self.view.addSubview(toDrag)
}

func panView(sender: UIPanGestureRecognizer) {
    guard let senderView = sender.view else { return }

    if sender.state == .recognized { print("Pan Recognized", terminator:"")}
    if sender.state == .began { print("Pan began", terminator: "") }
    if sender.state == .changed { print("Pan changed", terminator: "") }
    if sender.state == .ended { print("Pan ended", terminator: "") }

    let point = senderView.convert(senderView.center, to: nil)

    print (" point \(point)")
    let translation = sender.translation(in: self.view)
    senderView.center = CGPoint(x: senderView.center.x + translation.x, y: senderView.center.y + translation.y)
    sender.setTranslation(CGPoint.zero, in: self.view)
}
}

MyView

import UIKit

class MyView: UIView {

var isAnimated: Bool = false

override init(frame: CGRect) {
    super.init(frame: frame) // calls designated initializer
    self.isOpaque = false
    self.backgroundColor = UIColor.clear
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.isOpaque = false
    self.backgroundColor = UIColor.clear
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    isAnimated = true
    rotate1()
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    isAnimated = false
    endRotation()
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    isAnimated = false
    endRotation()
}

override func draw(_ rect: CGRect) {
    guard let context = UIGraphicsGetCurrentContext() else {return}
    context.addEllipse(in: rect)
    context.setLineWidth(1.0)
    context.setStrokeColor(UIColor.black.cgColor)
    context.setFillColor(UIColor.red.cgColor)
    context.drawPath(using: .fillStroke)
}

func rotate1() {
    guard isAnimated else { return }
    UIView.animate(withDuration: 0.05, delay:0.0, options: [], animations: {
        self.transform = CGAffineTransform.init(rotationAngle:.pi/16).scaledBy(x: 1.5, y: 1.5)
    }, completion: { _ in
        self.rotate2()
    })
}

func rotate2() {
    guard isAnimated else { return }
    UIView.animate(withDuration: 0.05, delay:0.0, options: [], animations: {
        self.transform = CGAffineTransform.init(rotationAngle:.pi/(-16)).scaledBy(x: 1.5, y: 1.5)
    }, completion: { _ in
        self.rotate1()
    })

}
func endRotation () {
    // End existing animation
    UIView.animate(withDuration: 0.5, delay:0.0, options: .beginFromCurrentState, animations: {
        self.transform = CGAffineTransform.init(rotationAngle:0 ).scaledBy(x: 1, y: 1)
    }, completion: nil)
}
}

With this version, here are some displays of the position

Pan began point (233.749182687299, 195.746572421573)
Pan changed point (175.265022520054, 181.332358181369)
Pan changed point (177.265022520054, 184.332358181369)
Pan changed point (177.265022520054, 184.332358181369)
Pan changed point (178.265022520054, 185.332358181369)
Pan changed point (179.265022520054, 186.332358181369)
Pan changed point (180.265022520054, 187.332358181369)
Pan changed point (180.265022520054, 188.332358181369)
Pan changed point (181.265022520054, 188.332358181369)
Pan RecognizedPan ended point (181.265022520054, 189.332358181369)

You can see that the first position (began point) isn't correct: the view was animated at that moment. The other positions are OK, when dragging, the view don't animate.

If I comment the code in rotate1 and rotate2, all the positions are correct, so I assume that the sizing and eventually the rotation of the view are interfering in the result. My question is: how can I retrieve the correct position of the view, when it is scaled? Obviously, the line

senderView.convert(senderView.center, to: nil)

didn't make what I thought : converting the coordinate to the fixed size screen coordinates?

COMENTARIOS

DEJA TU COMENTARIO

© 2017 website by Rubit Corporation