У меня есть пользовательское представление CustomLayout (синий, пользовательский UIView), и это представление содержит 3 подпредставления, выровненные по вертикали с использованием ограничений (привязок макета), каждое представление выровнено в следующем порядке:
- 1 просмотр: SlideLayout (красный, пользовательский UIView)
- 2 вид: UIButton (желтый)
- 3 вид: UIView (сухой серый)
Я хочу, чтобы при нажатии на кнопку (желтая) размер высоты SlideLayout (красный) увеличивался при открытии или уменьшался при закрытии с использованием анимации. И другие виды должны изменить положение во время анимации, и родительский вид (CustomLayout) должен увеличить / уменьшить его размер высоты (анимация), если SlideLayout увеличивается / уменьшается.
Какой метод вызывается при использовании этого метода:
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)
}
}