Автоматическая компоновка просмотров с анимацией - PullRequest
0 голосов
/ 08 мая 2018

У меня есть пользовательское представление 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)
    }
}

1 Ответ

0 голосов
/ 08 мая 2018

Если вы хотите создать динамический вид, не меняйте фрейм, а изменяйте константу ограничения, так как фрейм не сдвигает родительский элемент вниз, поэтому установите ограничение высоты представления, которое вы хотите анимировать, как IBOutlet и контролировать его постоянное значение

Вы можете попробовать

class CustomLayout: UIView {

   var heightCon:NSLayoutConstraint!

    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
                   heightCon =  child.heightAnchor.constraint(equalToConstant: child.frame.size.height) 
                   heightCon.isActive = true 
                }

//

    public func slideAnimation() {
        print("\(HEIGHT)")

         isClosed = !isClosed

         let ss = self.superview as! CustomLayout

         ss.heightCon.constant = self.isClosed ? 0 : self.HEIGHT

         UIView.animate(withDuration: 1, delay: 0, options: .curveEaseInOut, animations: { 
            ss.layoutIfNeeded()
         }, completion: nil)
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...