【问题标题】:Animate NSView constraints (layer backed view) on macOS objective-cmacOS 上的动画 NSView 约束(图层支持视图)objective-c
【发布时间】:2020-10-29 09:15:41
【问题描述】:

我使用的是 XCode 12、macOS、objective-c,而不是 iOS。

我有一个包含 3 个项目的菜单(水平堆栈视图):

蓝色下划线是以编程方式创建的:

- (void)viewDidLoad {

    [super viewDidLoad];     
    [self createAnimatedLineAtButton:self.importButton];
}

// Create line
- (void)createAnimatedLineAtButton:(NSButton*)button {

    // This view is layer backed
    SHViewCustomBackground* underlineView = [[SHViewCustomBackground alloc] init];
    
    underlineView.backgroundColor = [NSColor colorNamed:@"color_spot"]; // blue color
    underlineView.translatesAutoresizingMaskIntoConstraints = NO;
    [self.view addSubview:underlineView];
    self.underlineView = underlineView;    

    [self updateAnimatedLineUnderButton:self.importButton];
}

接下来的代码会更新约束(最初在上面的行创建中调用),然后在单击每个按钮时更新。

- (void)updateAnimatedLineUnderButton:(NSButton *)button {
    
    // Constraints are stored here
    if (self.underlineConstraints) {
        [self.view removeConstraints:self.underlineConstraints];
    }

    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){
        context.duration = 1;
        context.allowsImplicitAnimation = YES;
    
        NSView* underlineView = self.underlineView;
        NSDictionary *views = NSDictionaryOfVariableBindings(underlineView, button);
        self.underlineConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[button]-[underlineView(1)]" options:NSLayoutFormatAlignAllLeading | NSLayoutFormatAlignAllTrailing metrics:nil views:views];
        [self.view addConstraints:self.underlineConstraints];
    
        [self.view layoutSubtreeIfNeeded];
    } completionHandler:nil];    
}

这里是按钮操作

- (IBAction)buttonClicked:(id)sender {
    
    [self updateAnimatedLineUnderButton:(NSButton*)sender];
}

现在我的问题:当我按此顺序单击“导入”>“导出”>“导入”按钮时,该行按预期从导入到导出并返回动画。每当我点击“占位符”(中间按钮)时,这条线就会跳跃并且没有动画。当我点击“导入”或“导出”之后它也会跳转。

我想知道这里有什么问题。所有按钮连接正确,所有动作都正确触发。

编辑:在比较所有按钮后,我发现导入和导出按钮(它工作的地方)具有相同的宽度。

【问题讨论】:

  • 我看到下划线的宽度在动画中也发生了变化,并注意您对宽度的评论。也许对齐到中心并将宽度设置为两个单独的显式约束(或者现在甚至只是给它一个固定宽度)然后看看它是如何进行的?
  • 它以固定宽度工作。即使对齐中心约束与“button-equalWidth”相结合也不起作用。每当涉及到动态宽度时,它都会显示 GIF 中的行为。不幸的是,我希望动态宽度使用不同的字符串长度进行本地化
  • 如果你做分割动画应该可以工作 - 也许更新你的代码?也可能将 layoutSubtree 移动到完成块?
  • LayoutSubtree 触发动画......因此不能进入完成块。分割动画是什么意思?
  • 我的意思是你分别为宽度和中心对齐约束设置动画。

标签: objective-c constraints core-animation nsview


【解决方案1】:

这是一个想法......它有效。最初我打算按照你的方式做,但你可能不喜欢这样,最终动画了两个约束。但是效果很好。

这个想法与你的非常相似,但这里的不同之处在于我创建了一个前导和一个尾随约束,并改为对其进行动画处理。

@implementation ViewController

- ( void ) viewDidLoad
{
    super.viewDidLoad;
    [self animateLine:self.longButton];
}

// Animate the line
- ( void ) animateLine:( NSButton * ) button
{
    [NSAnimationContext runAnimationGroup: ^ ( NSAnimationContext * context ) {

        context.duration = 1;
        context.allowsImplicitAnimation = YES;
        self.leadingConstraint.animator.constant = button.frame.origin.x;
        self.trailingConstraint.animator.constant = self.stackView.bounds.size.width - button.frame.origin.x - button.frame.size.width;
        NSLog ( @"Setting leading to %f trailing to %f", self.leadingConstraint.constant, self.trailingConstraint.constant );

        self.lineField.layoutSubtreeIfNeeded;

    }];
}

- ( IBAction ) buttonAction:( id ) sender
{
    [self animateLine:sender];
}

就是这样。其余的发生在故事板中。我设置了约束,以便通过交换第一个和第二个项目来使距离有意义。

【讨论】:

  • 这很棒。虽然我想在代码中而不是在 IB 中创建所有内容。
  • 嘿嘿嘿,你喜欢受苦……我在故事板中做了尽可能多的事情,只是为了节省时间和测试这个想法。这也是我最终这样做的原因,因为它是最快的。我认为您可以轻松地将其转换为代码。
  • 我将尝试在 viewdidload 上设置约束并将它们保存在一些引用指针中。如果这有效,我将明确接受您的答案,因为它已被证明有效。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多