Search code examples
iosswiftautolayoutuicontrol

Height constraint animation 'jumping'


I've been creating my own UIControl subclass for use in my tweak iDunnoU. I've finished the UIControl, with the exception of the expand/collapse animation. The issue with this animation is that it 'jumps' down/up when expanding/collapsing, instead of fanning out smoothly like my original mockup (see below).

I have uploaded the code to a GitHub repository, found here. The code for adding the control to the superview can be found here, the code for setting up the height constraint can be found here, and the code for animating the height constraint can be found here.

Mockup iDunnoUMenuButton


Solution

  • UIView.animate() can be a little tricky -- you need to call .layoutIfNeeded() on the correct view.

    Replace your isExpanded / didSet in iDUMenuButton class with this:

    var isExpanded = false {
        didSet {
            if isExpanded != oldValue {
                if isExpanded {
                    becomeFirstResponder()
                    let haptics = UIImpactFeedbackGenerator(style: .rigid)
                    haptics.impactOccurred()
                }
                guard let sv = self.superview else {
                    // shouldn't happen, but let's be thorough
                    fatalError("Self must have a superview!!!")
                }
                // not needed
                //self.layoutIfNeeded()
                UIView.animate(withDuration: 0.3) {
                    self.heightConstraint.isActive = !self.isExpanded
    
                    // call .layoutIfNeeded() on self's superview
                    //self.layoutIfNeeded()
                    sv.layoutIfNeeded()
    
                    self.layer.shadowOpacity = self.isExpanded ? 1 : 0
                    self.buttons.forEach { $0.setBadgeHidden(hidden: !self.isExpanded, animated: true) }
                }
                delegate?.menuButton(self, isExpandedDidUpdate: isExpanded)
            }
        }
    }