【发布时间】:2018-05-08 19:38:58
【问题描述】:
我有一个自定义视图,CustomLayout(蓝色,自定义 UIView),该视图包含 3 个使用约束(布局锚)垂直对齐的子视图,每个视图都按照以下顺序对齐:
- 1 个视图:SlideLayout(红色,自定义 UIView)
- 2 视图:UIButton(黄色)
- 3 视图:UIView(干灰色)
我希望当我点击按钮(黄色)时,SlideLayout(红色)的高度大小在打开时增加或在关闭时通过动画减小。如果SlideLayout增加/减少,其他视图必须在动画期间改变位置,并且父视图(CustomLayout)必须增加/减少他的高度大小(动画)。
我使用这个方法的时候调用了什么方法:
UIView.animate(withDuration、延迟、选项、动画、完成)
我通过添加一个简单的打印来覆盖 layoutIfNeeded() 方法,但它不会在动画期间每次都调用
我尝试了这个,但它没有像我预期的那样工作。我该如何解决这个问题,谢谢。
代码:
class CustomLayout: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private func setup() {
onLayout()
}
public func onLayout() {
print("\(frame.size.height)")
let MARGIN: CGFloat = 10
for i in 0 ..< subviews.count {
let child = subviews[i]
if i == 0 { // slide layout
child.translatesAutoresizingMaskIntoConstraints = false
child.topAnchor.constraint(equalTo: topAnchor, constant: MARGIN).isActive = true
child.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
child.widthAnchor.constraint(equalToConstant: frame.size.width - (MARGIN * 2)).isActive = true
let enchorHeight = child.heightAnchor.constraint(equalToConstant: child.frame.size.height);
enchorHeight.isActive = true
(subviews[0] as! SlideDownLayout).enchorHeight = enchorHeight
}
else if i == 1 { // button
child.translatesAutoresizingMaskIntoConstraints = false
child.topAnchor.constraint(equalTo: subviews[0].bottomAnchor, constant: MARGIN).isActive = true
child.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
child.widthAnchor.constraint(equalToConstant: child.frame.size.width).isActive = true
child.heightAnchor.constraint(equalToConstant: child.frame.size.height).isActive = true
}
else if i == 2 { // uiview
child.translatesAutoresizingMaskIntoConstraints = false
child.topAnchor.constraint(equalTo: subviews[1].bottomAnchor, constant: MARGIN).isActive = true
child.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
child.widthAnchor.constraint(equalToConstant: frame.size.width - (MARGIN * 4)).isActive = true
child.heightAnchor.constraint(equalToConstant: 300).isActive = true
bottomAnchor.constraint(equalTo: child.bottomAnchor, constant: MARGIN).isActive = true
}
}
}
}
class SlideDownLayout: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
private var HEIGHT: CGFloat = 0
private var isClosed: Bool = true
private func setup() {
HEIGHT = frame.height
frame.size.height = 0
}
public func slideAnimation(view: UIView) {
print("\(HEIGHT)")
isClosed = !isClosed
self.enchorHeight!.constant = self.isClosed ? 0 : self.HEIGHT
UIView.animate(withDuration: 1, delay: 0, options: .curveEaseInOut, animations: {
self.superview?.layoutIfNeeded()
view.layoutIfNeeded()
}, completion: nil)
}
override func layoutIfNeeded() {
print("...")
super.layoutIfNeeded()
}
var enchorHeight: NSLayoutConstraint? = nil
}
class ViewController: UIViewController {
@IBOutlet weak var customLayout: CustomLayout!
@IBOutlet weak var slideDownLayout: SlideDownLayout!
override func viewDidLoad() {
super.viewDidLoad()
customLayout.translatesAutoresizingMaskIntoConstraints = false
customLayout.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
customLayout.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
customLayout.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
customLayout.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
}
override var prefersStatusBarHidden: Bool {
return true
}
@IBAction
func buttonListener(_ sender: Any) {
slideDownLayout.slideAnimation(view: self.view)
}
}
【问题讨论】:
-
用stackView试试这个
标签: ios swift animation autolayout