使用具有约束持续时间的动画在 swift 中移动按钮并在此期间检测触摸

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

我想将一个按钮从 A 点移动到 B 点。A 点:leadingConstraint = 120, topConstraint = 400。 B 点:leadingConstraint = 120, topConstraint = 200。为了我的游戏目的,我不能使用框架。我还希望能够在它移动时检测到它的触摸(我不知道该怎么做)。我有这段代码,我试图移动按钮(使用带持续时间的动画)但发生的事情是它从左上角(小尺寸)开始而不是从 A 点开始。然后它转到 B 点(正常尺寸)。这是代码:

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

请帮忙。我也不想使用 CADisplayLink。提前致谢...安东

你的问题有3个问题:

  1. 按钮必须从 A 点开始,而不是从左上角开始。
  2. 按钮必须是正常尺寸,不能是小尺寸。
  3. 按钮在移动时可以点击

对于 (1) 和 (2),您必须移动代码以在 viewDidLoad() 内添加按钮,并且还需要为 buttontopAnchorForButton.[=26 保留实例=]

首先,您为 buttontopAnchorForButton 声明两个属性。

var button: UIButton!
var topAnchorForButton: NSLayoutConstraint!

接下来,添加按钮并设置其在 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)]
}

对于(3),要点击一个移动的按钮,你需要在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)
    }
}

如果您想在每次按下开始按钮时都创建一个新按钮,请将要添加的代码放入 start: 方法中并设置其位置。您不再需要为 buttontopAnchorForButton 保留实例。您可以使用标签来检索按钮。

@IBAction func start(sender: AnyObject) {
    // Remove the previous button
    if let previousButton = self.view.viewWithTag(100) as? UIButton {
        previousButton.removeFromSuperview()
    }

    let button = UIButton()
    button.tag = 100 // Set a tag so you can retrieve the button
    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

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

    self.view.layoutIfNeeded()

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

更新 touchesBegan:withEvent event:

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

    guard let button = self.view.viewWithTag(100) as? UIButton else {
        return
    }

    let touchLocation = touch.locationInView(self.view)
    if button.layer.presentationLayer()?.hitTest(touchLocation) != nil {
        self.buttonPressed(button)
    }
}

请注意,如果您不喜欢使用标签来检索按钮,您可以为按钮声明一个属性。