2017-05-15 4 views
0

Ich habe Probleme beim Abrufen der aktuellen Position einer Ansicht, absolut im iPhone-Bildschirm, wenn die Ansicht skaliert wird. Hier ist ein minimales Beispiel von dem, was ich getan habe.Abrufen der richtigen Position einer skalierten UIView

Ich habe eine einzige elliptische Ansicht auf dem Bildschirm. Wenn ich tippe, wächst es und beginnt zu zittern, um zu zeigen, dass es ausgewählt ist. Dann kann ich die Ansicht über den ganzen Bildschirm ziehen.

Hier ist der 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) 
} 
} 

Mit dieser Version sind hier einige Anzeigen der 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) 

Sie können sehen, dass die erste Position (Anfangspunkt) nicht korrekt ist: Die Ansicht wurde in diesem Moment animiert. Die anderen Positionen sind in Ordnung, beim Ziehen wird die Ansicht nicht animiert.

Wenn ich den Code in rotate1 und rotate2 kommentiere, sind alle Positionen korrekt, also nehme ich an, dass die Dimensionierung und eventuell die Rotation der Ansicht das Ergebnis stört. Meine Frage ist: Wie kann ich die richtige Position der Ansicht abrufen, wenn sie skaliert ist? Offensichtlich ist die Linie

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

nicht machen, was ich dachte: Umwandlung der auf die festen Größe Bildschirmkoordinaten koordinieren?

+1

Wenn Sie die Transformation einer Ansicht ändern, wird der Rahmen ungültig, aber das Zentrum sollte immer noch korrekt sein. Ich glaube, wenn Sie die Ansicht übersetzen, wird auch der Mittelpunkt übersetzt, aber ich bin nicht davon überzeugt. Es ist ein bisschen schwer, den Daten zu folgen, die du zeigst und zu erzählen, was passiert. –

+0

Ich erkläre meine Ziele: In der Tat ist die Ansicht ein Pfand, und der Bildschirm ist ein Brett. Ich wollte also wissen, wo sich der Bauer bewegt und wo er endet. Die Animation dient nur dazu, visuell zu prüfen, ob der gute Bauer ausgewählt wurde. Die Quellen sind vollständig: Sie können ein neues Projekt erstellen, ViewController-Quelle ersetzen, MyView-Datei hinzufügen und es sollte wie auf meinem Computer funktionieren. – FredericP

Antwort

0

abrufen In der Tat hatte ich ein anderes Problem mit der Ansicht konvertieren (Retrieve the right position of a subView with auto-layout) und mein Problem war das gleiche, also ist die Lösung hier ...

Ich habe die Methode nicht korrekt verwendet. Wenn ich mit der beninho85 Lösung (und noch sauberer cosyn Methode nur eine Ansicht verwenden) ändern, funktioniert es! Ich kann die richtigen Koordinaten haben, auch wenn die Ansicht animiert ist.

Ich hatte gerade zu ersetzen, in Viewcontroller:

let Punkt = senderView.convert (senderView.Zentrum, zu: nil)

mit

let Punkt = senderView.convert (CGPoint (x: senderView.bounds.midX, y: senderView.bounds.midY), zu: nil)

0

Ich habe versucht, die Animation von Animation in Kern Animation (Layer) zu ändern, und das Ergebnis war das gleiche. So

Ich habe versucht, eine Formel vorstellen, mit Größe, Grenzen und Rahmenwerten, die in der richtigen Position zur Folge haben könnten, aber ich war nicht erfolgreich ...

Das einzige, das funktionierte, war sofort zu stoppen die Animation mit einer Transformation, kurz vor dem Versuch, das Zentrum, wie das in PANVIEW

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

    // Stop the transformation now! 
    senderView.transform = CGAffineTransform.init(rotationAngle:0).scaledBy(x: 1, y: 1) 

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

Es ist nicht die Lösung, die ich wollte, aber ich gehe mit diesem jetzt ...

Verwandte Themen