【问题标题】:Retrieving the right position of a scaled UIView检索缩放的 UIView 的正确位置
【发布时间】:2017-10-14 20:02:02
【问题描述】:

当视图缩放时,我无法检索视图的当前位置,绝对是在 iPhone 屏幕中。 这是我所做的一个最小示例。

我在屏幕上有一个椭圆视图。当我点击时,它会变大并开始颤抖以表明它已被选中。然后我可以将视图拖到整个屏幕上。

代码如下:

视图控制器

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

我的视图

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

在这个版本中,这里有一些位置的显示

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)

您可以看到第一个位置(开始点)不正确:视图在那一刻是动画的。其他位置没问题,拖的时候视图不动画。

如果我在 rotate1 和 rotate2 中注释代码,所有位置都是正确的,所以我假设视图的大小调整和最终的旋转会干扰结果。我的问题是:如何在缩放时检索视图的正确位置?很明显,这条线

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

没有按照我的想法:将坐标转换为固定大小的屏幕坐标?

【问题讨论】:

  • 当你改变视图的变换时,它的框架变得无效,但中心仍然应该是正确的。我相信,如果您翻译视图,那么中心点也会被翻译,但我对此并不肯定。但是,要跟踪您显示的数据并了解正在发生的事情有点困难。
  • 我解释一下我的目标:实际上,视图是棋子,屏幕是棋盘。所以我想知道棋子从哪里开始移动,在哪里结束。动画仅用于目视检查是否选择了好棋子。源是完整的:你可以创建一个新的项目,替换 viewcontroller 源,添加 MyView 文件,它应该像在我的机器上一样工作。

标签: ios swift uiview position scale


【解决方案1】:

我尝试将动画从View动画改为Core Animation(layer),结果还是一样。

所以我试着想象一个公式,包含大小、边界和框架值,可以得出正确的位置,但我没有成功......

唯一可行的方法是在尝试检索中心之前立即通过变换停止动画,就像在 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:"")}
    ...

这不是我想要的解决方案,但我现在就这样做......

【讨论】:

    【解决方案2】:

    事实上,我在视图转换方面遇到了另一个问题 (Retrieve the right position of a subView with auto-layout) 和我的问题一样,所以解决方法就在这里...

    我没有正确使用该方法。如果我使用beninho85 的解决方案进行更改(甚至更清洁cosyn 的方法只使用一个视图),它就可以工作!即使视图是动画的,我也可以获得正确的坐标。

    我只需要在 ViewController 中替换:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      • 2014-06-17
      • 2015-04-22
      • 2015-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多