Cocoa Autolayout:在运行时以编程方式插入(和删除)视图

时间:2014-04-09 14:54:55

标签: macos cocoa autolayout nsscrollview

我对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.predicateEditorHeight是对IBOutlet高度的约束NSScrollView。 然后在封闭的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 )>

1 个答案:

答案 0 :(得分:1)

你必须通知&#39;父视图,内部视图将调整大小。我的方法是通过其代表观察谓词的增长和缩小:

- (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];
}

观察者&#39;在父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];
}];

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

祝你好运。