【问题标题】:Cocoa Autolayout: insert (and remove) view programmatically at runtimeCocoa Autolayout:在运行时以编程方式插入(和删除)视图
【发布时间】:2014-04-09 14:54:54
【问题描述】:

我对 Cocoa Autolayout 有一些问题。 我有一个窗口,我(以编程方式)添加了一个NSTableView(及其NSScrollView)。到现在为止一切正常。我可以调整窗口大小,并且表格可以正确调整大小。 这是我使用的代码。

MyListViewController *viewController = [[MyListViewController alloc] initWithNibName:@"ListView" bundle:nil];

[self.mainContentView addSubview:viewController.view];
[viewController.view setTranslatesAutoresizingMaskIntoConstraints:NO];

[self.mainContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[insertedView]|"
                                                                                 options:0
                                                                                 metrics:nil
                                                                                   views:@{@"insertedView" :viewController.view}]];
NSArray *verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[insertedView]|"
                                                                           options:0
                                                                           metrics:nil
                                                                             views:@{@"insertedView" :viewController.view}];

[self.mainContentView addConstraints:verticalConstraints];

现在.. 我想在运行时添加(和删除)另一个放置在表格顶部的视图。 视图是 NSPredicateEditor 及其 NSScrollView。需要明确的是:当您在搜索字段中键入内容并且带有可能搜索选项的视图出现在主窗口中时,我正在尝试实现与 Finder 相同的行为。

我是这样处理的:

AdvancedFilterViewController *viewController = [[AdvancedFilterViewController alloc] initWithNibName:@"AdvancedFilterView" bundle:nil];

[self.mainContentView addSubview:viewController.view];
[viewController.view setTranslatesAutoresizingMaskIntoConstraints:NO];

[self.mainContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[insertedView]|"
                                                                             options:0
                                                                             metrics:nil
                                                                               views:@{@"insertedView" :viewController.view}]];
[self.mainContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[insertedView(<=225)][prevView]|" // >= size of one row, <= size of 8 + 1 rows
                                                                             options:0
                                                                             metrics:nil
                                                                               views:@{@"insertedView" :viewController.view, @"prevView" : self.listView.view}]];

我希望至少有一行谓词(25 分)是可见的。当用户按下加号按钮时,会开始出现更多视图(并且滚动视图应该调整其大小)。几行之后(我决定 9 行),滚动条应该开始出现,并且窗口中的主视图应该停止缩小。

问题是当我插入过滤视图时,它的大小几乎为零(如 1 点)。或者如果我添加最小大小为 25 点,视图是可见的,但添加行只会增加滚动视图的“内部大小”,因此出现滚动条(但滚动视图不会增长并且不会使列表视图缩小) .

我希望我正确地解释了这个问题。

编辑:

从我实现委托的答案中获得灵感:

- (void)ruleEditorRowsDidChange:(NSNotification *)notification
{
    //handle resizing of the view
    [self.predicateEditorHeight setConstant:[self.predicateEditor numberOfRows] * self.predicateEditor.rowHeight];
}

其中self.predicateEditorHeightIBOutletNSScrollView 高度的约束。 然后在封闭的NSWindowController 中,当我添加谓词编辑器视图时,我还添加了对NSTableView 相对于谓词视图的比例的约束。 通过这种方式(因为我将它设置为 0.3)滚动视图可以增长到某个点,然后,它必须使用它的滚动条。

我仍然有一些关于约束的问题: 例如,当我在编辑器中添加太多行时,我得到

2014-04-26 09:38:27.769 MyApp[2531:303] Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x60000029dc40 V:[NSView:0x60000013fb80]-(0)-|   (Names: '|':NSView:0x60000013e500 )>",
    "<NSLayoutConstraint:0x60000029dbf0 V:[NSView:0x600000320b40]-(0)-[NSView:0x60000013fb80]>",
    "<NSLayoutConstraint:0x60000029dc90 NSView:0x60000013fb80.height >= 0.3*NSView:0x600000320b40.height>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000288b60 h=--& v=--& V:[NSView:0x60000013e500(360)]>",
    "<NSLayoutConstraint:0x60000029dba0 V:|-(0)-[NSView:0x600000320b40]   (Names: '|':NSView:0x60000013e500 )>",
    "<NSLayoutConstraint:0x60000029d1a0 V:[NSView:0x600000320f00(275)]>",
    "<NSLayoutConstraint:0x60000029d420 V:[NSView:0x600000320f00]-(0)-|   (Names: '|':NSView:0x600000320b40 )>",
    "<NSLayoutConstraint:0x60000029d510 V:[NSView:0x600000320dc0]-(0)-[NSView:0x600000320f00]>",
    "<NSLayoutConstraint:0x60000029d330 V:|-(0)-[NSView:0x600000320dc0]   (Names: '|':NSView:0x600000320b40 )>",
    "<NSLayoutConstraint:0x60000029d060 V:[NSButton:0x6000001569a0'Search']-(4)-|   (Names: '|':NSView:0x600000320dc0 )>",
    "<NSLayoutConstraint:0x60000029d0b0 V:|-(5)-[NSButton:0x6000001569a0'Search']   (Names: '|':NSView:0x600000320dc0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000029d060 V:[NSButton:0x6000001569a0'Search']-(4)-|   (Names: '|':NSView:0x600000320dc0 )>

2014-04-26 09:38:27.770 MyApp[2531:303] Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x60000029dc40 V:[NSView:0x60000013fb80]-(0)-|   (Names: '|':NSView:0x60000013e500 )>",
    "<NSLayoutConstraint:0x60000029dbf0 V:[NSView:0x600000320b40]-(0)-[NSView:0x60000013fb80]>",
    "<NSLayoutConstraint:0x60000029dc90 NSView:0x60000013fb80.height >= 0.3*NSView:0x600000320b40.height>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000288b60 h=--& v=--& V:[NSView:0x60000013e500(360)]>",
    "<NSLayoutConstraint:0x60000029dba0 V:|-(0)-[NSView:0x600000320b40]   (Names: '|':NSView:0x60000013e500 )>",
    "<NSLayoutConstraint:0x60000029d1a0 V:[NSView:0x600000320f00(275)]>",
    "<NSLayoutConstraint:0x60000029d420 V:[NSView:0x600000320f00]-(0)-|   (Names: '|':NSView:0x600000320b40 )>",
    "<NSLayoutConstraint:0x60000029d510 V:[NSView:0x600000320dc0]-(0)-[NSView:0x600000320f00]>",
    "<NSLayoutConstraint:0x60000029d330 V:|-(0)-[NSView:0x600000320dc0]   (Names: '|':NSView:0x600000320b40 )>",
    "<NSLayoutConstraint:0x60000029d100 V:|-(4)-[NSButton:0x6000001564d0]   (Names: '|':NSView:0x600000320dc0 )>",
    "<NSLayoutConstraint:0x60000029d150 V:[NSButton:0x6000001564d0]-(5)-|   (Names: '|':NSView:0x600000320dc0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000029d150 V:[NSButton:0x6000001564d0]-(5)-|   (Names: '|':NSView:0x600000320dc0 )>

2014-04-26 09:38:27.775 MyApp[2531:303] Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x60000029cf70 V:[NSTextField:0x600000198940]-(4)-|   (Names: '|':NSView:0x600000320dc0 )>",
    "<NSLayoutConstraint:0x60000029cfc0 V:|-(4)-[NSTextField:0x600000198940]   (Names: '|':NSView:0x600000320dc0 )>",
    "<NSLayoutConstraint:0x60000029dc40 V:[NSView:0x60000013fb80]-(0)-|   (Names: '|':NSView:0x60000013e500 )>",
    "<NSLayoutConstraint:0x60000029dbf0 V:[NSView:0x600000320b40]-(0)-[NSView:0x60000013fb80]>",
    "<NSLayoutConstraint:0x60000029dc90 NSView:0x60000013fb80.height >= 0.3*NSView:0x600000320b40.height>",
    "<NSAutoresizingMaskLayoutConstraint:0x608000288b60 h=--& v=--& V:[NSView:0x60000013e500(360)]>",
    "<NSLayoutConstraint:0x60000029dba0 V:|-(0)-[NSView:0x600000320b40]   (Names: '|':NSView:0x60000013e500 )>",
    "<NSLayoutConstraint:0x60000029d1a0 V:[NSView:0x600000320f00(275)]>",
    "<NSLayoutConstraint:0x60000029d420 V:[NSView:0x600000320f00]-(0)-|   (Names: '|':NSView:0x600000320b40 )>",
    "<NSLayoutConstraint:0x60000029d510 V:[NSView:0x600000320dc0]-(0)-[NSView:0x600000320f00]>",
    "<NSLayoutConstraint:0x60000029d330 V:|-(0)-[NSView:0x600000320dc0]   (Names: '|':NSView:0x600000320b40 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x60000029cf70 V:[NSTextField:0x600000198940]-(4)-|   (Names: '|':NSView:0x600000320dc0 )>

【问题讨论】:

  • 观察您的 AutoresizingMaskLayouts - 您是否已在所有相关视图中将 TranslatesAutoresizingMaskIntoConstraints 设置为 NO?
  • 可以在IB中设置吗?还是我必须以编程方式进行? (所以你的问题的答案是否定的:))
  • 您可以在 IB 中以编程方式设置它。在 IB 打开视图的属性检查器并找到“将掩码转换为约束”。在代码中,您已经设置了视图:setTranslatesAutoresizingMaskIntoConstraints:NO]。但这是正确的观点吗?尝试将其设置为父级或谓词 - 视图。
  • 我设法找到了复选框。不幸的是,什么都没有改变。但是日志中仍然出现了一些掩码约束,不,也许我没有删除所有这些约束。我将不得不花一些时间在这上面。谢谢

标签: macos cocoa autolayout nsscrollview


【解决方案1】:

您必须“通知”父视图,内部视图将调整大小。我的方法是通过它的委托来观察谓词的增长和收缩:

- (void)ruleEditorRowsDidChange:(NSNotification *)notification{

  NSInteger newRowCount = [_predicateEditor numberOfRows];
  NSInteger rowHeight = [_predicateEditor rowHeight];

  // Send a notification - size changes
  NSRect newFrame = self.view.frame;
  newFrame.size.height = 30 + newRowCount*rowHeight;
  [[NSNotificationCenter defaultCenter]postNotificationName:@"RowsDidChange" object:[NSValue valueWithRect:newFrame]];
  [[_heightConstraint animator] setConstant:rowHeight*newRowCount];
}

在父 ViewController 中还有一个“观察者”来观察尺寸变化:

 [[NSNotificationCenter defaultCenter]addObserverForName:@"RowsDidChange" 
    object:nil 
    queue:nil 
    usingBlock:^(NSNotification * notification){
        NSValue *value =  (NSValue*)notification.object;
        NSRect rectValue = [value rectValue];

        NSRect newContentRect = self.resultsView.frame;
        newContentRect.size.height = self.resultsView.frame.size.height - rectValue.size.height;
        newContentRect.size.width = self.resultsView.frame.size.width;

        // Set new height to the mainViewController
        [[self.mainViewController view] setFrame:newContentRect];
}];

你不需要发送通知,你也可以发送一些委托方法给你的父视图控制器。

祝你好运。

【讨论】:

  • 谢谢。我几乎解决了这个问题。我仍然对约束有一些问题。也许其他一些提示可以帮助我:)
猜你喜欢
  • 1970-01-01
  • 2021-07-12
  • 1970-01-01
  • 2015-10-07
  • 2010-09-27
  • 1970-01-01
  • 2011-02-16
  • 2017-03-10
  • 1970-01-01
相关资源
最近更新 更多