iOS约束动画没有立即发生

时间:2015-08-14 16:28:08

标签: objective-c swift animation uiview nslayoutconstraint

基本上,我使用两个不同的约束让UIView滑入和滑出(从左到右或从右到左)

然而,飞行中的动画应该停在那里,并立即开始向相反的方向设置动画,因为我操纵了约束并调用了layoutIfNeeded:。

奇怪的是,新动画需要一些时间才能生效。旧动画将慢慢停止。这就像UIView有一些“惯性”,不能立即停止。

这是为什么?这可以通过简单的方式解决吗?我试过了

"UIViewAnimationOptions.BeginFromCurrentState" - not working.

谈话很便宜,告诉你代码:

请打开“Xcode iOS单视图项目”并将所有代码粘贴到“ViewController.swift”。你没有其他任何改变。 您可以多次在模拟器中下拉绿色视图并检查此动画问题。

//
//  ViewController.swift
//  testItem
//
//  Created by 陈成 on 15/8/11.
//  Copyright © 2015年 陈成. All rights reserved.
//

import UIKit


class ccControl: UIControl {

    var imageView: UIImageView!
    var firstPoint: CGPoint!

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.backgroundColor = UIColor.blueColor()

        imageView = UIImageView()
        imageView.frame = CGRectMake(10, -363, 60, 438)
        imageView.backgroundColor = UIColor.greenColor()
        self.addSubview(imageView)
    }

    override func intrinsicContentSize() -> CGSize {
        return CGSizeMake(80, 175)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }


    override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        print("beginTrackingWithTouch")
        let touchPoint = touch.locationInView(self)

        if CGRectContainsPoint(imageView.frame, touchPoint) {
            firstPoint = touchPoint
            return true
        }

        return false
    }

    override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
        let touchPoint = touch.locationInView(self)
        var dy = touchPoint.y - firstPoint.y

        dy = max(dy, 0)
        dy = min(dy, self.bounds.size.height - 75)

        self.imageView.frame = CGRectMake(10, dy + 75 - 438, 60, 438)

        if dy > 75 {
            self.sendActionsForControlEvents(UIControlEvents.ValueChanged)

            UIView.animateWithDuration(1.0, animations: { self.imageView.frame = CGRectMake(10, 75 - 438, 60, 438) }, completion: nil)

            return false
        }
        return true
    }
}

class ViewController: UIViewController {

    var status = "a"
    var hid: NSLayoutConstraint!
    var sho: NSLayoutConstraint!

    override func viewDidAppear(animated: Bool) {

        super.viewDidAppear(animated)
        let cd = ccControl()
        cd.translatesAutoresizingMaskIntoConstraints = false
        cd.addTarget(self, action: "vc", forControlEvents: UIControlEvents.ValueChanged)
        self.view.addSubview(cd)

        let hiddenView = UIView()
        hiddenView.backgroundColor = UIColor.purpleColor()
        hiddenView.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(hiddenView)

//        add constraints
        self.view.addConstraint(NSLayoutConstraint(item: cd, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: topLayoutGuide, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0))



        hid = NSLayoutConstraint(item: hiddenView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 0)
        sho = NSLayoutConstraint(item: hiddenView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)

        self.view.addConstraint(hid)

        self.view.addConstraint(NSLayoutConstraint(item: hiddenView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100))

        self.view.addConstraint(NSLayoutConstraint(item: hiddenView, attribute: NSLayoutAttribute.Right, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Right, multiplier: 1, constant: 0))
        self.view.addConstraint(NSLayoutConstraint(item: hiddenView, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 0))

        self.view.layoutSubviews()
    }

    func vc() {

    switch status {
        case "a":
            status = "b"
            self.view.removeConstraint(hid)
            self.view.addConstraint(sho)


        case "b":
            status = "a"
            self.view.removeConstraint(sho)
            self.view.addConstraint(hid)
    default:
        break
    }

        self.view.setNeedsLayout()

//        UIView.animateWithDuration(10, delay: 0, options: [UIViewAnimationOptions.BeginFromCurrentState, UIViewAnimationOptions.AllowAnimatedContent, UIViewAnimationOptions.AllowUserInteraction], animations: {
//            for i in self.view.subviews {
//                i.layer.removeAllAnimations()
//            }
//       
//            self.view.layoutIfNeeded()
//            }, completion: nil)



        UIView.animateWithDuration(10.0) {
            self.view.layoutIfNeeded()
        }

    }

}

2 个答案:

答案 0 :(得分:0)

  

layoutIfNeeded强制接收者立即布置其子视图,如果需要

您可能需要致电setNeedsLayout。试试这个:

self.view.setNeedsLayout()
UIView.animateWithDuration(20.0) {
    self.view.layoutIfNeeded()
}

答案 1 :(得分:0)

documentation而言,您需要在开始动画约束之前调用layoutIfNeeded。然后,如果需要,它将完成从动画中重绘内容,然后您的视图应该准备好立即制作动画。

view.layoutIfNeeded()
// make some constraint changes

UIView.animateWithDuration(20.0) {
    self.view.layoutIfNeeded()
}