使用带有约束的持续时间动画快速移动按钮并在其中检测触摸

Posted

技术标签:

【中文标题】使用带有约束的持续时间动画快速移动按钮并在其中检测触摸【英文标题】:Moving a button in swift using animate with duration with constraints and detecting a touch during it 【发布时间】:2016-01-02 02:02:17 【问题描述】:

我想将按钮从 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。在此先感谢...安东

【问题讨论】:

【参考方案1】:

您的问题有 3 个问题:

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

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

首先,为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)
    

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

【讨论】:

非常感谢!很好的描述! 1 个问题:如果我想在每次按下开始按钮时创建一个新按钮,我必须在代码中进行哪些更改?

以上是关于使用带有约束的持续时间动画快速移动按钮并在其中检测触摸的主要内容,如果未能解决你的问题,请参考以下文章

单击时隐藏和显示 div,带有绝对位置的动画,并在隐藏时将其删除

使用带有自动布局的推送时隐藏按钮时,约束更新导致项目移动

使用约束向目标移动按钮,没有反应?

如何让我的动画功能快速依赖于客观的 c mic 打击检测?

带有子 UIView(保存内容)的 UIScrollView 未检测到点击

检测在移动设备上离开全屏 iframe