如何将居中的方形设置为顶部

我有一个只有肖像的应用程序UIView

  • 视图以垂直水平方向 居中 放置 AutoLayout (使用故事板“手动”)。
  • width等于(main)view.width * 0.9
  • height是相同的宽度(这是一个正方形)的大小。

我想在这个UIView里面点击一个button,并且只是垂直地animation它,直到它到达屏幕的顶部边界(例如height * 0.9,10 pts,无论怎样)。

当我再次点击时,我想重新定位视图到原来的位置(居中,就像我第一次点击时那样)。

在过渡期间,广场不应该放倒。

在阅读了很多post后,我无法理解这样做的最好方法是什么(我主要是开发者说使用centerX旧技术应该避免,并且对某些版本的SO以奇怪的方式performance感到悲叹)。

我想我应该find一种方法来获得约束的当前“位置”,并将约束分配给“最终”位置,但是我无法做到这一点。

任何帮助表示赞赏

虽然你可以使用Autolayoutanimation – 约束约束中心Y和设置其常数值将移动到顶部(例如, constant = -(UIScreen.main.bounds.height / 2) ),我会build议使用视图的transform属性。

所以要将视图移动到顶端,您可以使用:

 let topMargin = CGFloat(20) let viewHalfHeight = self.view.bounds.height / 2 let boxHalfHeight = self.box.bounds.height / 2 UIView.animate(withDuration: 0.2) { box.transform = CGAffineTransform.identity .translatedBy(x: 0, y: -(viewHalfHeight - (boxHalfHeight + topMargin))) } 

你正在移动与box.center相关的view.center – 所以如果你想要移动框到顶端,你必须移动它的center一半的视图的高度(因为视图的中心centerYheight / 2远离视图top )。 这是不够的,因为那么只有框的下半部分是可见的(现在box.centerY == view.top )。 因此,您必须将其移回box.bounds.height / 2 (在我的代码boxHalfHeight ) – 使上半部分可见。 而对于boxHalfHeight你添加topMargin以便有一些边缘的顶部。

然后,将box移回到原来的位置:

 UIView.animate(withDuration: 0.2) { box.transform = CGAffineTransform.identity } 

编辑

如果你真的想要自动布局,你必须有一个centerY约束的引用,例如,如果它是这样创build的:

 let boxCenterYConstraint = self.box.centerYAnchor.constraint(equalTo: self.view.centerYAnchor) boxCenterYConstraint.isActive = true 

那么你可以试试这个:

 // calculating the translation is the same let topMargin = CGFloat(20) let viewHalfHeight = self.view.bounds.height / 2 let boxHalfHeight = self.box.bounds.height / 2 let diff = -(viewHalfHeight - (boxHalfHeight + topMargin)) boxCenterYConstraint.constant = diff self.view.setNeedsLayout() UIView.animate(withDuration: 0.2) { self.view.layoutIfNeeded() } 

和animation回来:

 boxCenterYConstraint.constant = 0 self.view.setNeedsLayout() UIView.animate(withDuration: 0.2) { self.view.layoutIfNeeded() } 

这一切都是错误的。

添加一个将视图固定到顶部的约束,并添加一个将视图固定到centerY 。 它会抱怨,所以select一个并禁用它(我认为Interface Builder中的属性被称为Installed )。

如果初始状态是中间的视图,则禁用将其固定到顶部的约束,反之亦然。

现在在您的控制器中为这两个约束编写IBOutlets并将它们连接到这些约束。 确保该variables的声明不weak ,否则当约束被禁用时variables将变为零。

每当你想切换你的animation,你可以启用一个约束,禁用另一个。

 @IBOutlet var topConstraint: NSLayoutConstraint! @IBOutlet var centerConstraint: NSLayoutConstraint! func toggleState(moveToTop: Bool) { UIView.animateWithDuration(0.25) { self.topConstraint.isActive = moveToTop self.centerConstraint.isActive = !moveToTop self.view.layoutIfNeeded() } }