当前位置: 首页 > 知识库问答 >
问题:

如何在Swift中设置带有约束的UIView动画?

谭彦
2023-03-14

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

如您所见,它由几个简单的约束组成:

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

我想要实现的是让这个红色/粉红色的视图从顶部“进来”。传统上,在一个没有约束的世界中,我只需修改UIView内部的框架。animateWithDuration,但我不确定在约束世界中如何进行类似操作。

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

我考虑过设置垂直中心约束的动画(并随后调用layoutifneed),但没有达到预期效果。

谢谢你的帮助。

共有3个答案

皮骏
2023-03-14

试试这个:

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()
        }
    }

}

注意约束中的第一项和第二项顺序。以上代码假定Superview是第一项:

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

  • 中心Y对齐约束(Superview.CenterY==View.CenterY)优先级=750

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

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()
        }
    }

}
解晟睿
2023-03-14

你想要的其实很简单,我将详细说明如何做到这一点,而不干扰优先级或时髦的常数。这样我们就可以得到一个可以在任何屏幕大小上工作的动画。

TL; DR是你需要配置你的约束,然后在你的动画块中调用layoutIfNeed来动画修改。更多信息请参见这篇SO文章。

所以我们需要两组约束来隐藏和显示视图。在viewdiload中,视图将被隐藏,然后在viewdilead中出现或我们希望该视图滑入的任何位置。

因此,第一件事是配置在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)
}

同样,我们的show约束将把视图的中心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)
}
尉迟高澹
2023-03-14

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

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

UIView.animateWithDuration(Double(0.5), animations: {
        self.centerYConstraint.constant = 0
        self.view.layoutIfNeeded()
    })
 类似资料:
  • I'hv 4s。所有这些都在父中。父有它的固定高度约束,即240。但是我必须将它最小化到190iPhone4。 子视图的高度是固定的。现在我的问题是,如何在父视图中设置所有4个UIView,使其具有相同的间距,以便如果我只更改其父视图的高度,子视图可以自动适应其父视图中的相同间距。 提前非常感谢。 父视图约束: 领先0 尾随0 顶部到它的父母X 底部到它的父母Y 高度240(我必须在iPhone4

  • 我有一个,我想在点击时放大它的宽度。我设置了约束,并确保左侧的约束优先级低于我试图在右侧设置动画的约束优先级。 这是我试图使用的代码。 这是可行的,但似乎只是瞬间发生,似乎没有任何运动。我试着将其设置为10秒,以确保没有遗漏任何内容,但我得到了相同的结果。 是我控制的从IB拖到我的类中的约束的名称。

  • 虽然有几个问题的答案与我的相似,但似乎没有一个能解决我的困境。我有一个图像视图,我可以通过改变水平和垂直约束来移动它,并使用长按手势在屏幕上移动。如果这张图像没有移动一定的距离,我希望它能动画化回到原来的位置。我正在使用以下代码示例来尝试执行此操作: 和在其他地方定义为用户单击的位置 和定义为用户在超级视图中的位置 不用说,平移图像时,一切都正常。它会拖动,然后在手势结束时停止。问题是,如果用户没

  • 我在viewcontroller的中央有一个UITextField(搜索字段),我正在使用UIView(liveView)创建一条细线。我以编程方式创建线视图及其约束。lineView本质上是一个下划线,当用户键入时,它在文本字段下的宽度会增加。用户按enter键后,我将调整约束,以便文本字段和视图移动到viewcontroller的顶部。我让它工作起来了,但随着线视图向上移动,它开始淡出并消失。

  • 我放在表格视图中的代码:cellForRowAtIndexPath:- 要查看UITableViewCell中的任何动画,应该使用哪种方法或放置哪种类型的动画。我知道我无法设置现有标签的动画,因为这些标签带有约束。

  • 问题内容: 我正在使用来更新旧的应用,并且当没有广告时,它会滑出屏幕。出现广告时,它会在屏幕上滑动。基本的东西。 旧样式,我将帧设置在动画块中。新样式,我对自动布局约束有一个确定Y位置,在这种情况下,它是距父视图底部的距离,并修改常量: 横幅完全按预期移动,但没有动画。 更新:我重新观看了WWDC 12讲的“掌握自动布局的最佳实践” ,其中涵盖了动画。它讨论了如何使用CoreAnimation更新