Anton O. Anton O. - 4 years ago 213
Swift Question

Moving a button in swift using animate with duration with constraints and detecting a touch during it

I want to move a button from point A to point B. Point A:

leadingConstraint = 120, topConstraint = 400
. Point B:
leadingConstraint = 120, topConstraint = 200
. For my game purpose, I can't use frames. I also want to be able to detect a touch on it while its moving (I have no idea how to do this). I have this code where I'm attempting to move the button (using animate with duration) but whats happening is that its starting from the top left corner (small size) instead of starting from point A. It then goes to point B (normal size). Here is the code:

@IBAction func Start(sender: UIButton) {
var topAnchorforButton: NSLayoutConstraint!
let button = UIButton()
button.setTitle("button", forState: .Normal)
button.setTitleColor(UIColor.blackColor(), forState: .Normal)
button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
topAnchorforButton = button.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 400)
NSLayoutConstraint.activateConstraints([
button.widthAnchor.constraintEqualToConstant(75),
button.heightAnchor.constraintEqualToConstant(75),
button.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: 120),
topAnchorforButton
])
[UIView.animateWithDuration(5.0, delay: 0.0, options: [.CurveLinear, .AllowUserInteraction], animations: {
topAnchorforButton.constant = 200
self.view.layoutIfNeeded()
}, completion: nil)]
}
func buttonPressed(sender: UIButton) {
print("hi")
}


Please help. I also don't want to use
CADisplayLink
. Thanks in advance... Anton

Answer Source

There are 3 issues in your question:

  1. The button must start from point A instead of the top left corner.
  2. The button must have a normal size instead of a small size.
  3. The button can be able to click while its moving.

For (1) and (2), you must move code to add button inside the viewDidLoad() and also need to keep instances for button and topAnchorForButton.

Firstly, you declare two properties for button and topAnchorForButton.

var button: UIButton!
var topAnchorForButton: NSLayoutConstraint!

Next, you add button and set its position inside the viewDidLoad().

override func viewDidLoad() {
    super.viewDidLoad()

    button = UIButton()
    button.setTitle("button", forState: .Normal)
    button.setTitleColor(UIColor.blackColor(), forState: .Normal)
    button.addTarget(self, action: "buttonPressed:", forControlEvents: UIControlEvents.TouchUpInside)
    self.view.addSubview(button)
    button.translatesAutoresizingMaskIntoConstraints = false

    topAnchorForButton = button.topAnchor.constraintEqualToAnchor(view.topAnchor, constant: 400)
    NSLayoutConstraint.activateConstraints([
        topAnchorForButton,
        button.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor, constant: 120),
    ])
}

func buttonPressed(sender: UIButton) {
    print("hi")
}

@IBAction func start(sender: AnyObject) {
    topAnchorForButton.constant = 200

    [UIView.animateWithDuration(5.0, delay: 0.0, options: [.CurveLinear, .AllowUserInteraction], animations: {
        self.view.layoutIfNeeded()
        }, completion: nil)]
}

For (3), to hit a moving button, you need to do hit testing on the button's .layer.presentationLayer property.

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    guard let touch = (touches as NSSet).anyObject() as? UITouch else {
        return
    }

    let touchLocation = touch.locationInView(self.view)
    if button.layer.presentationLayer()?.hitTest(touchLocation) != nil {
        self.buttonPressed(button)
    }
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download