调用touchesBegan时,动画UIView对象会跳转

时间:2017-08-14 03:02:32

标签: ios swift animation touchesbegan

我有一个UILabel对象正在动画,上下移动。我使用Swift 3在Xcode 8.3中编码。用户可以平移此对象并拖动到一个位置以获得一些点。我正在使用touchesXXX手势处理平移/拖动。然而,当我点击并让它立即行进时,由于某种原因,这个物体在其位置上方垂直跳跃,我现在无法弄清楚为什么一周...

当我启用一些调试时,我只能看到touchesBegan被调用(touchesMoved没有按预期调用,touchesEnded对我来说都不是意外的。如果我手动禁用对象上的动画,它会按预期工作,并且该对象可以毫不费力地进行平移,并且显然没有对象跳转。

以下是相关代码的摘录:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    let touchLocation = touch!.location(in: self.view)

    if self.optOneLbl.layer.presentation()!.hitTest(touchLocation) != nil {
        //pauseLayer(self.optOneLbl.layer)      <<<<< comment #1
        //optOneLbl.translatesAutoresizingMaskIntoConstraints = true      <<<<< comment #2
        optOneLbl.center = touchLocation
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    let touchLocation = touch!.location(in: self.view)
    var sender: UILabel

    if self.optOneLbl.layer.presentation()!.hitTest(touchLocation) != nil {
        self.optOneLbl.center = touchLocation
        sender = self.optOneLbl
    }

    // identify which letter was overlapped
    var overlappedView : UILabel
    if (sender.frame.contains(letter1.center)) {
        ...
    }
    else {
        return
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
}

在阅读了对其他SO问题的回复后,我认为按照上面touchesBegan中的评论#1触摸时,以编程方式禁用标签动画可能会有所帮助,但问题仍然存在。此外,我认为可能是自动布局导致这种奇怪的跳跃。所以,我根据评论#2启用了translatesAutoresizingMaskIntoConstraints,但它也没有帮助。

任何人都能看到我处理错误的地方? 谢谢你的阅读!

编辑:

根据@ agibson007请求,我添加动画代码提取以供参考:

UIView.animate(withDuration: 12.0, delay: 0.0, options: [ .allowUserInteraction, .curveLinear, .autoreverse, .repeat ], animations: {
    self.optOneLbl.center = CGPoint(x: self.optOneLbl.center.x, y: screenSize.midY*1.1)
})

2 个答案:

答案 0 :(得分:1)

更改标签的位置后,您需要删除/重置动画。动画不知道您更新了值并且尝试从头开始保持在相同的byValue范围内。这是更新动画的工作示例。

import UIKit

class ViewController: UIViewController {

    var optOneLbl = UILabel()


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.


        optOneLbl = UILabel(frame: CGRect(x: 20, y: 50, width: self.view.bounds.width - 40, height: 40))
        optOneLbl.textAlignment = .center
        optOneLbl.text = "I Will Be Moving Up and Down"
        optOneLbl.textColor = .white
        optOneLbl.backgroundColor = .blue
        self.view.addSubview(optOneLbl)

        //starts it in the beginnning with a y
        fireAnimation(toY:  self.view.bounds.midY*1.1)


    }

    func fireAnimation(toY:CGFloat) {
        UIView.animate(withDuration: 12.0, delay: 0.0, options: [ .allowUserInteraction, .curveLinear, .autoreverse, .repeat ], animations: {
            self.optOneLbl.center = CGPoint(x: self.optOneLbl.center.x, y:toY)
        })
    }



    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self.view)

        if self.optOneLbl.layer.presentation()!.hitTest(touchLocation) != nil {
            //re
            optOneLbl.layer.removeAllAnimations()
            optOneLbl.center = touchLocation
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self.view)
        var sender: UILabel

        if self.optOneLbl.layer.presentation()!.hitTest(touchLocation) != nil {
            self.optOneLbl.center = touchLocation
            sender = self.optOneLbl
        }
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        //restart animation after finished and change the Y if you want.  
        // you could change duration or whatever
        fireAnimation(toY: self.view.bounds.height - optOneLbl.bounds.height)
    }

}

答案 1 :(得分:0)

您可以使用UIPanGestureRecognizer实现相同目的。在您的标签上添加平移手势,并将标签移动到平底锅上

@IBAction func handlePan(_ gestureRecognizer: UIPanGestureRecognizer) {
    if gestureRecognizer.state == .began || gestureRecognizer.state == .changed {

        let translation = gestureRecognizer.translation(in: self.view)
        yourLabel!.center = CGPoint(x: yourLabel!.center.x + translation.x, y: yourLabel!.center.y + translation.y)
        gestureRecognizer.setTranslation(CGPoint.zero, in: self.view)
    }
}

您可以从故事板向您的UILabel添加gesturerecognizer,或在viewDidLoad中以编程方式添加

let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
yourLabel.addGestureRecognizer(gestureRecognizer)

使用Pan手势作为您不必跟进touchesXX方法的优势。为什么你的观点正在向上移动,我认为你可能会在其他地方重置你的标签框架。手势也有可能与触摸相冲突。由于这两种情况在您的代码中都不明显,我们需要更多代码来确认相同的内容。