Search code examples
xcodeswiftanimationuibarbuttonitemuitoolbar

UIView snaps back to original frame when UIBarButton is pressed


At the top of my UIView called "courseView", I have a toolbar with a bar button called "expand button". When I press that button, expandCourseView() is called and the view frame animates properly. However upon completion of the animation, I would like the "expandButton" to change text. When it does this, the view's frame automatically snaps back to its original shape. Why does this happen? It seems as if the button on the toolbar does not register that its location has shifted.

@IBOutlet weak var expandButton: UIBarButtonItem!

@IBAction func expandButton(sender: AnyObject) {
    expandCourseView()
}

func expandCourseView(){
    let width = self.courseView.frame.width
    let height = self.courseView.frame.height
    let frameOffset : CGFloat = 200
    UIView.animateWithDuration(0.5, animations: { () -> Void in
        if (height < 211){
            self.courseView.frame = CGRect(x: self.courseView.frame.minX, y: self.courseView.frame.minY - frameOffset, width: width, height: height + frameOffset)
        }
        else {
            self.courseView.frame = CGRect(x: self.courseView.frame.minX, y: self.courseView.frame.minY + frameOffset, width: width, height: height - frameOffset)
        }
        }) { (value: Bool) -> Void in
            if height < 211{
                self.expandButton.title = "Close"
            } else {
                self.expandButton.title = "Expand"
            }
    }
}

Solution

  • You're probably using auto layout. Although you can manipulate frames directly to animate or move views, at some point something (like setting a label's text value) will call setNeedsLayout() and cause the view to restore to the values specified by the constraints.

    You can leave your animation as-is, but in the completion (or in updateConstraints()) you'll need to modify the constraints to keep the views in their new position.