简体   繁体   中英

UIView animation with autolayout and child views

I have a weird problem that seems to be fairly easy to solve. I think I could use some workaround to be able to have the behavior that I want but I want to know if there is a better way to do it.

I have a view called contentView (blue in the image) that it will expand its height using a UIView.animation, this is no problem at all and works as expected.

The problem here is that this view has a child component (a button) that has an autolayout constraint to its bottom equal to 22 like this:

使用按钮的contentView

This is the autolayout constraint:

在此处输入图片说明

If I do the height resize without the animation it works fine, the view height change and the button are always 22 points of the bottom of the contentView. But when I use an animation to make this change more smoothy and user-friendly the button moves to the end position before the animation even start.

在此处输入图片说明

I want to know how I could achieve a smooth animation here but with the button moving along its parent view

The part of the code that handles the animation is pretty straightforward but I'll post it in here:

@IBAction func openDetail(_ sender: ExpandCourseDetail) {
        let rotation = sender.getOpen() ? CGAffineTransform.identity : CGAffineTransform(rotationAngle: CGFloat.pi)
        UIView.animate(withDuration: 0.5, delay: 0.1, options: [.curveEaseInOut], animations: {
            sender.transform = rotation
        }, completion: {
            success in
            sender.setOpen(!sender.getOpen())
        })
        UIView.animate(withDuration: 1.0, delay: 0.5, options: [.curveEaseInOut], animations: {
            self.contentView.frame.size.height = sender.getOpen() ? self.contentView.frame.height - 300 : self.contentView.frame.height + 300
        }, completion: nil)
    }

As a side note, the button itself has an animation that rotates the button 180 degrees to show the user that the view is expanding.

Thank you so much for your help.

It's super easy with constraints, just create a superView height constraint IBOutlet and change its constant value.

@IBAction func btnPressed(_ sender: UIButton) {
    self.toggleButton.isSelected = !sender.isSelected

    //Animation starts here
    self.view.layoutIfNeeded()
    UIView.animate(withDuration: 0.7) {

        if self.toggleButton.isSelected {
            //transform button
            self.toggleButton.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi))

            //change your ParentView height to desired one
            self.constContentViewHeight.constant = self.view.frame.size.height - 220
            self.view.layoutIfNeeded()
        } else {

            self.toggleButton.transform = CGAffineTransform(rotationAngle: CGFloat(Double.pi*2))
            // Set height constraint to original value
            self.constContentViewHeight.constant = 250
            self.view.layoutIfNeeded()
        }
    }

}

I have created a demo, check it out.

演示

The issue you are facing is due to two animation blocks. So I have changed some lines and put both button transformation and height animation into one animation block.

func openDetail(_ sender: ExpandCourseDetail) {

    let isOpen = sender.getOpen() ? CGAffineTransform.identity : CGAffineTransform(rotationAngle: CGFloat.pi)

    UIView.animate(withDuration: 1.0, delay: 0.5, options: [.curveEaseInOut], animations: {

        sender.transform = rotation
        self.contentView.frame.size.height = self.contentView.frame.height + (isOpen ? 300 : -300)

    }, completion: { (success) in
        sender.setOpen(!isOpen)
    })
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM