UIView height constraint animation, which has anchor connection with other views

Xcode swift 4

I have some views that are added dynamically in code one below another. Each new view top anchor is connected to previous view bottom anchor. And each view have a button that make view to expand/collapse with animation. Here is button code :

    let fullHeight : CGFloat = 240
    let smallHeight : CGFloat = 44

    let currentHeigth  = rootView.frame.size.height //I use this to get current height and understand expanded view or not

    let heighCons = rootView.constraints.filter //I use this to deactivate current height Anchor constraint
    {
        $0.firstAttribute == NSLayoutAttribute.height
    }
    NSLayoutConstraint.deactivate(heighCons)
    rootView.layoutIfNeeded()

    if currentHeigth == smallHeight
    {
        rootView.heightAnchor.constraint(equalToConstant: fullHeight).isActive = true
        rootView.setNeedsLayout()

        UIView.animate(withDuration: 0.5)
        {
            rootView.layoutIfNeeded() //animation itself
        }

    }
    else
    {
        rootView.heightAnchor.constraint(equalToConstant: smallHeight).isActive = true
        rootView.setNeedsLayout()

        UIView.animate(withDuration: 0.5)
        {
            rootView.layoutIfNeeded() //animation itself
        }
    }

This all works perfectly but i have a problem : view that below current expanding view changes it y position immediately with no animation. Its just jumping to previous view bottom anchor, that would be active after animation finish.

So my question is :

1) what is the right way to make height constraint animation, when views are connected to each other by bottom/top animation?

2) my goal is just to make a view that would expand/collapse on button click, maybe i should do it another way?

1 answer

  • answered 2018-08-09 03:55 tabassum

    enter image description here
    enter image description here

    Here's an approach using Visiblity Gone Extension

    extension UIView {
    func visiblity(gone: Bool, dimension: CGFloat = 0.0, attribute: NSLayoutAttribute = .height) -> Void {
        if let constraint = (self.constraints.filter{$0.firstAttribute == attribute}.first) {
            constraint.constant = gone ? 0.0 : dimension
            self.layoutIfNeeded()
            self.isHidden = gone
        }
     }
    }
    

    Usage

    expanview.visiblity(gone: true,dimension: 0)
    

    Example

    @IBOutlet weak var msgLabel: UILabel!
    @IBOutlet weak var expanview: UIView!
    @IBAction func toggleCollapisbleView(_ sender: UIButton) {
        if sender.isSelected{
            sender.isSelected = false
            expanview.visiblity(gone: false,dimension: 128)
            sender.setTitle("Collapse",for: .normal)
        }
        else{
            sender.isSelected = true
            expanview.visiblity(gone: true,dimension: 0)
            sender.setTitle("Expand",for: .normal)
            msgLabel.text = "Visiblity gone"
        }
    
    }