如何在Swift中使用约束为UIView设置动画?

2020/12/13 23:22 · ios ·  · 0评论

在我的人为示例中,我有以下单个视图:

在此处输入图片说明

如您所见,它由一些简单的约束组成:

  1. 对齐水平和垂直中心,
  2. 高度(设置为常数)
  3. 前导和尾随空格(设置为常数)

我要实现的目标是从顶部“进入”这种偏红色/偏粉色的视图。传统上,在没有约束的世界中,我只会修改内的框架UIView.animateWithDuration,但是我不确定在约束世界中如何做类似的事情。

要重申我的问题,如何使我的视图脱离场景并为从顶部飞入的视图设置动画?

我已经考虑过对垂直中心约束进行动画处理(并随后调用layoutIfNeeded),但是并没有达到预期的效果。

谢谢你的帮助。

您可以做的是在您的viewDidAppear方法中添加以下代码首先,IBOutlet为视图的中心Y约束创建一个属性,然后更改其常数。

self.centerYConstraint.constant = 500.0
self.view.layoutIfNeeded()

UIView.animateWithDuration(Double(0.5), animations: {
        self.centerYConstraint.constant = 0
        self.view.layoutIfNeeded()
    })

实际上,您想要的是非常简单的,我将详细介绍如何做到这一点而又不会弄乱优先级或时髦的常量。这样,我们可以获得可以在任何屏幕尺寸上播放的动画。

TL; DR是您需要配置约束,然后在动画块内部调用layoutIfNeeded来对更改进行动画处理。有关更多信息,请参见此SO帖子

因此,我们需要两组约束来隐藏和显示视图。viewDidLoad视图中将被隐藏,然后在viewDidAppear我们希望该视图滑入的任何地方。

情节提要/ XIB设置

因此,第一件事是配置不会在IB(或代码,无论您喜欢哪种)中更改的约束。红色视图的高度及其到容器的前后空间。因此,您的约束可能看起来像这样(请注意:我尚未设置宽度约束,但让前导和尾随空格定义宽度):

约束条件

现在,您将看到IB会警告您,视图的Y位置没有配置约束(因此,红色虚线表示)

带有警告的视图

现在,您可以将顶部空间添加到容器约束中,并将其设置为占位符约束(显示“在构建时删除”的复选框)。之所以这样做,是因为我们要控制视图的编程位置。

在此处输入图片说明

这意味着,一旦加载视图,此约束将不存在,但可用来删除所有警告,因为您告诉IB知道在加载视图时如何处理此约束。

编码时间

现在我们需要一种隐藏视图的方法,一种显示视图的方法。为此,我们将在视图上存储Y定位约束,然后对其进行动画处理。我们的viewController可能看起来像这样:

@IBOutlet weak var redView: UIView!
var redViewYPositionConstraint: NSLayoutConstraint?

override func viewDidLoad() {
    super.viewDidLoad()
    self.hideRedViewAnimated(false)
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)
    self.showRedViewAnimated(true)
}

隐藏

我们隐藏视图的方法可以简单地删除位置约束,然后添加一个红色视图的底部等于视图控制器的视图顶部的视图:

func hideRedViewAnimated(animated: Bool) {
    //remove current constraint
    self.removeRedViewYPositionConstraint()
    let hideConstraint = NSLayoutConstraint(item: self.redView,
        attribute: .Bottom,
        relatedBy: .Equal,
        toItem: self.view,
        attribute: .Top,
        multiplier: 1,
        constant: 0)
    self.redViewYPositionConstraint = hideConstraint
    self.view.addConstraint(hideConstraint)
    //animate changes
    self.performConstraintLayout(animated: animated)
}

显示中

类似地,我们的显示约束会将视图的中心Y移动到控制器的中心Y:

func showRedViewAnimated(animated: Bool) {
    //remove current constraint
    self.removeRedViewYPositionConstraint()
    let centerYConstraint = NSLayoutConstraint(item: self.redView,
        attribute: .CenterY,
        relatedBy: .Equal,
        toItem: self.view,
        attribute: .CenterY,
        multiplier: 1,
        constant: 0)
    self.redViewYPositionConstraint = centerYConstraint
    self.view.addConstraint(centerYConstraint)
    //animate changes
    self.performConstraintLayout(animated: animated)
}

便利方法

为了完整起见,我使用的便捷方法如下所示:

func performConstraintLayout(animated animated: Bool) {
    if animated == true {
          UIView.animateWithDuration(1,
          delay: 0,
          usingSpringWithDamping: 0.5,
          initialSpringVelocity: 0.6,
          options: .BeginFromCurrentState,
          animations: { () -> Void in
             self.view.layoutIfNeeded()
          }, completion: nil)
     } else {
          self.view.layoutIfNeeded()
     }
}

func removeRedViewYPositionConstraint() {
    if redViewYPositionConstraint != nil {
        self.view.removeConstraint(self.redViewYPositionConstraint!)
        self.redViewYPositionConstraint = nil
    }
}

您还可以使用一些CGRect数学检查红色视图是否可见:

func isRedViewVisible() -> Bool {
    return CGRectContainsPoint(self.view.bounds, self.redView.frame.origin)
}

试试这个:

class ViewController: UIViewController {

    // red view
    @IBOutlet weak var myView: UIView!
    //  vertical align contraint
    @IBOutlet weak var verticalConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        verticalConstraint.constant = (myView.bounds.height + self.view.bounds.height)/2
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.view.layoutIfNeeded()
        UIView.animateWithDuration(0.5) {
            self.verticalConstraint.constant = 0
            self.view.layoutIfNeeded()
        }
    }

}

要小心firstItem,并secondItem在约束顺序。上面的代码假定Superview是firstItem

屏幕截图


另一种方法是定义两个约束:

  • 中心Y对齐约束(Superview.CenterY == View.CenterY)优先级= 750
  • 垂直空间限制(SuperView.Top == View.Bottom)优先级= 500

屏幕截图

并调整优先级,以确定应采用哪种约束。

class ViewController: UIViewController {

    //  vertical align contraint
    @IBOutlet weak var centerYConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()
        centerYConstraint.priority = 250
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.view.layoutIfNeeded()
        UIView.animateWithDuration(0.5) {
            self.centerYConstraint.priority = 750
            self.view.layoutIfNeeded()
        }
    }

}

对于希望像请求这样的简单动画的任何人:

对于上滑动画,您需要使用
CGAffineTransformMakeTranslation(x,y)

原因是对于上滑动画,您需要先将视图移出屏幕,然后再将其放回原始位置。因此,在您的viewDidLoad中,只需使用:

yourView.transform = CGAffineTransformMakeTranslation(0, 500)

这会将视图移出屏幕,在本例中为底部。现在,在
viewDidAppear中,您可以使用以下命令显示视图:

UIView.animateWithDuration(0.7, delay: 0.0, usingSpringWithDamping: 0.5,
initialSpringVelocity: 0.5, options: [], animations: {
        self.yourView.transform = CGAffineTransformMakeScale(1, 1)
    }, completion: nil)

通过这些行,您可以在UIView上添加所需的约束,并将其放置在ViewController中所需的位置。

对我而言,制作Swift 3和4动画的最佳方法

self.constraint.constant = -150

UIView.animate(withDuration: 0.45) { [weak self] in
    self?.view.layoutIfNeeded()
}
本文地址:http://ios.askforanswer.com/ruhezaiswiftzhongshiyongyueshuweiuiviewshezhidonghua.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 admin 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!