Joshua
Joshua

Reputation: 147

How to add a view in a NSStackView with animation?

In interface builder, I have several views (A, B, C) in a NSStackView (vertical orientation). During runtime, I change dynamically the NSStackView by showing or hiding (isHidden) some of these embedded views through a property observer (willSet). If the code below actually works (the views show or hide accordingly), I can't manage to do it with animation.

  var isExpanded :Bool = false {
        willSet {
            NSAnimationContext.beginGrouping()
            NSAnimationContext.current.duration = 2.0
            if newValue {
                viewA.isHidden = true
                viewB.isHidden = false
                viewC.isHidden = true
                viewD.isHidden = true
                print("Popover expanded")
            } else {
                viewA.isHidden = false
                viewB.isHidden = false
                viewC.isHidden = false
                viewD.isHidden = false
                print("Popover contracted")
            }
            NSAnimationContext.endGrouping()
        }

As I understand, the isHidden state is not handled by the animation but I don't find other ways to do it. Alternatively, I also tried to use addView and removeFromSuperview method (instead of hiding/showing). Same results...

My problem is that I mainly find iOS-related problems (UIView.animate...), and none about MacOS (NSView)...

Any ideas ?

Many thanks for your help, Jo

Upvotes: 2

Views: 905

Answers (1)

Joshua
Joshua

Reputation: 147

I had the wrong approach: isHidden is not the right approach (can't animate a discrete value - it's hidden or not). Instead, I added a constraint on the view's height Connect the constraint in the viewController as an IBOutlet. With this code, the view smoothly squeeze in between 2 other views in a stackView. :-)

@IBOutlet weak var constraint: NSLayoutConstraint!

@IBAction func toggle(_ sender: NSButton) {
    if constraint.constant == 0 {
        NSAnimationContext.runAnimationGroup({context in
            context.duration = 0.25
            context.allowsImplicitAnimation = true
            constraint.constant = 80
            self.view.layoutSubtreeIfNeeded()
        }, completionHandler: nil)

    } else {

        NSAnimationContext.runAnimationGroup({context in
            context.duration = 0.25
            context.allowsImplicitAnimation = true
            constraint.constant = 0
            self.view.layoutSubtreeIfNeeded()
        }, completionHandler: nil)   
    }
}

Hope it helps.

Jo

Upvotes: 1

Related Questions