Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hide view item of NSStackView with animation

I working with swift 4 for macOS and I would like to hide an stack view item with animation.

I tried this:

class ViewController: NSViewController {

    @IBOutlet weak var box: NSBox!
    @IBOutlet weak var stack: NSStackView!
    var x = 0



    @IBAction func action(_ sender: Any) {
        if x == 0 {

            NSAnimationContext.runAnimationGroup({context in
                context.duration = 0.25
                context.allowsImplicitAnimation = true

                self.stack.arrangedSubviews.last!.isHidden = true
                self.view.layoutSubtreeIfNeeded()
                x = 1
            }, completionHandler: nil)

        } else {

            NSAnimationContext.runAnimationGroup({context in
                context.duration = 0.25
                context.allowsImplicitAnimation = true

                self.stack.arrangedSubviews.last!.isHidden = false
                self.view.layoutSubtreeIfNeeded()
                x = 0
            }, completionHandler: nil)

        }

    }
}

The result will be:

enter image description here

It works! But I am not happy with the animation style. My wish is:

  • I press the button, the red view will be smaller to the right side
  • I press the button, the red view will be larger to the left side.

Like a sidebar or if you have an splitview controller and you will do splitviewItem.animator().isCollapsed = true

this animation of show/hide is perfect. Is this wish possible?

UPDATE self.stack.arrangedSubviews.last!.animator().frame = NSZeroRect

enter image description here

UPDATE 2

self.stack.arrangedSubviews.last!.animator().frame = NSRect(x: self.stack.arrangedSubviews.last!.frame.origin.x, y: self.stack.arrangedSubviews.last!.frame.origin.y, width: 0, height: self.stack.arrangedSubviews.last!.frame.size.height)

enter image description here

like image 581
Ghost108 Avatar asked Oct 18 '25 18:10

Ghost108


1 Answers

Have a look at Organize Your User Interface with a Stack View sample code.

I disliked the heightContraint on the view controller and the height calculation in the -viewDidLoad. The code below calculation the size before animating and only adds the contrain while animating.

Breakable Contraint

First you need to set the priority of the contraint to something lower than 1000 (required constraint) for the direction you want the animation. Here the bottom contraint.

While we animate the view in and out, we will add contraint to do so with a priority of 1000 (required constraint).

Code

@interface NSStackView (LOAnimation)
- (void)lo_toggleArrangedSubview:(NSView *)view;
@end

@implementation NSStackView (LOAnimation)
- (void)lo_toggleArrangedSubview:(NSView *)view
{
    NSAssert([self detachesHiddenViews], @"toggleArrangedSubview requires detachesHiddenViews YES");
    NSAssert([[self arrangedSubviews] containsObject:view], @"view not an arrangedSubview");
    CGFloat postAnimationHeight = 0;
    NSLayoutConstraint *animationContraint = nil;
    if (view.hidden) {
        view.hidden = NO; // NSStackView will re-add view to its subviews
        [self layoutSubtreeIfNeeded]; // calucalte view size
        postAnimationHeight = view.bounds.size.height;
        animationContraint = [view.heightAnchor constraintEqualToConstant:0];
        animationContraint.active = YES;
    } else {
        [self layoutSubtreeIfNeeded];  // calucalte view size
        animationContraint = [view.heightAnchor constraintEqualToConstant:view.bounds.size.height];
        animationContraint.active = YES;
    }
    [self layoutSubtreeIfNeeded]; // layout with animationContraint in place
    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context) {
        context.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
        animationContraint.animator.constant = postAnimationHeight;
        [self layoutSubtreeIfNeeded];
    } completionHandler:^{
        view.animator.hidden = (postAnimationHeight == 0);
        [view removeConstraint:animationContraint];
    }];
}
@end
like image 50
catlan Avatar answered Oct 21 '25 12:10

catlan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!