cocoa - NSLayoutConstraint.constant 忽略动画

标签 cocoa core-animation autolayout nsanimationcontext

我正在为我的一个应用程序创建一个自动布局友好的分割 View 类。它的各种功能之一是它可以折叠 Pane ,并可以为它们的折叠设置动画,就像您可能已经看到 NSSplitView 所做的那样。

由于我使用约束,因此我通过在 Pane 上放置所需的宽度 =(当前宽度)约束来实现此目的,然后以动画方式将约束的常量设置为 0:

- (NSLayoutConstraint*)newHiddenConstraintAnimated:(BOOL)animated {
    NSLayoutConstraint * constraint = [NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:NSWidth(self.view.frame)];
    constraint.priority = NSLayoutPriorityRequired;

    CABasicAnimation * anim = [CABasicAnimation animation];
    anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
    anim.duration = 0.2;
    constraint.animations = [NSDictionary dictionaryWithObject:anim forKey:@"constant"];

    [self.view addConstraint:constraint];

    [(animated ? constraint.animator : constraint) setConstant:0.0];

    return constraint;
}

这效果很好。不幸的是,稍后扩展 Pane 的效果并不好。

- (void)removeHiddenConstraintAnimated:(BOOL)animated {
    if(!animated) {
        [self.view removeConstraint:self.hiddenConstraint];
    }
    else {
        NSLayoutConstraint * constraint = self.hiddenConstraint;
        NSView * theView = self.view;

        [NSAnimationContext beginGrouping];

        [constraint.animator setConstant:self.width];

        [NSAnimationContext currentContext].completionHandler = ^{
            [theView removeConstraint:constraint];
        };

        [NSAnimationContext endGrouping];
    }

    self.hiddenConstraint = nil;
}

如果我插入一些计时代码,我可以看到完成处理程序几乎立即触发,在有时间制作动画之前删除约束。在 NSAnimationContext 上设置持续时间没有效果。

知道我在这里可能做错了什么吗?

最佳答案

您必须首先设置完成处理程序,然后才将消息发送到动画代理。否则,似乎在动画开始后设置完成处理程序会立即触发它,并且在动画有时间完成之前删除常量。 我刚刚用一段简单的代码检查了这一点:

[NSAnimationContext beginGrouping];
NSAnimationContext.currentContext.duration = animagionDuration;
NSAnimationContext.currentContext.completionHandler = ^{
  [self removeConstraint:collapseConstraint];
};
[collapseConstraint.animator setConstant:expandedHeight];

[NSAnimationContext 结束分组]; 这工作得很好,但如果你在 -setConstant: 之后设置完成处理程序,动画就没有机会运行。

关于cocoa - NSLayoutConstraint.constant 忽略动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9492467/

相关文章:

ios - CALayer似乎保留了它的内容——如何释放资源?

ios - 编程自动布局更改 UIView 的行为

objective-c - NSWindow 不会在 OSStatus 事件处理程序方法中显示

objective-c - 如何使用按钮移动图像?

cocoa - 尝试获取 textView macOS 的插入点

ios - 有没有办法用关键点进行 3D 变换?

ios - 使用编程自动布局调整 UITableView 的大小

swift - 在自动布局中更改宽度的 UILabel 问题

macos - 获取 OS X 上的型号标识符字符串

objective-c - 将 NSArray 中包含的字符串分配给不同 NSArray 中包含的对象