可可自动布局:插入(和删除)在运行时编程观点 [英] Cocoa Autolayout: insert (and remove) view programmatically at runtime

查看:133
本文介绍了可可自动布局:插入(和删除)在运行时编程观点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有可可自动布局的一些问题。
我有一个窗口,我想补充(编程)一个 NSTableView的(其 NSScrollView )。到现在为止一切正常。我可以调整我的窗口和表正确调整大小。
这是code我用。

  MyListViewController *的viewController = [[MyListViewController页头] initWithNibName:@ListView控件捆绑:无];[self.mainContentView addSubview:viewController.view];
[viewController.view setTranslatesAutoresizingMaskIntoConstraints:NO];[self.mainContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| [insertedView] |
                                                                                 选项​​:0
                                                                                 指标:无
                                                                                   观点:@ {@insertedView:viewController.view}]];
NSArray的* verticalConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@V:| [insertedView] |
                                                                           选项​​:0
                                                                           指标:无
                                                                             观点:@ {@insertedView:viewController.view}];[self.mainContentView addConstraints:verticalConstraints];

现在..我想在运行时添加(和删除),它被放置在表的顶部另一种观点。
视图是一个 NS predicateEditor NSScrollView 。需要明确的是:我试图实现取景器相同的行为,当你键入搜索字段的东西和可能的搜索选项的视图显示在主窗口

我用这种方式处理这个问题:

  AdvancedFilterViewController *的viewController = [[AdvancedFilterViewController页头] initWithNibName:@AdvancedFilterView捆绑:无];[self.mainContentView addSubview:viewController.view];
[viewController.view setTranslatesAutoresizingMaskIntoConstraints:NO];[self.mainContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@H:| [insertedView] |
                                                                             选项​​:0
                                                                             指标:无
                                                                               观点:@ {@insertedView:viewController.view}]];
[self.mainContentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@V:| [insertedView(小于= 225)] [prevView] | //> =大小一排,< =大小的8 + 1行
                                                                             选项​​:0
                                                                             指标:无
                                                                               观点:@ {@insertedView:viewController.view,@prevView:self.listView.view}]];

我想predicate(25分)是可见的,至少一个线路。当用户presses的加号按钮,然后更多的意见开始出现(和滚动视图应该调整其大小)。一些行之后(我决定9)滚动条开始出现,并在窗口中的主视图应该停止萎缩。

问题是,当我插入过滤器来看,它几乎是零的大小(如1点)。或者,如果我加25分的最小尺寸,视图是可见的,但添加行仅仅增加了滚动型的'内部尺寸',所以会出现滚动条(但滚动视图不长,不会使列表视图收缩)

我希望我正确地说明了问题。

编辑:

拍摄灵感来自于我的答案实现的委托:

   - (无效)ruleEditorRowsDidChange:(NSNotification *)的通知
{
    //视图的手柄大小调整
    [自predicateEditorHeight setConstant:。[自predicateEditor numberOfRows] *自predicateEditor.rowHeight]。
}

其中,的自己。predicateEditorHeight IBOutlet中来的<$ C的高度约束$ C> NSScrollView 。
然后在封闭 NSWindowController ,当我添加了predicate编辑观点我也对 NSTableView的相对于在predicate视图。
在这种方式(因为我将其设置为0.3)滚动视图可以生长,直到某一点,然后,在这之后,它必须使用其滚动

我仍然有限制的一些问题:
例如,当我在编辑器中添加过多的行,我得到

  2014年4月26日09:38:27.769的MyApp [2531:303]无法同时满足约束条件:

    &LT; NSLayoutConstraint:0x60000029dc40五:[的NSView:0x60000013fb80] - (0) - |(名称:'|':一个NSView:0x60000013e500)&gt;中,
    &所述; NSLayoutConstraint:0x60000029dbf0五:[的NSView:0x600000320b40] - (0) - [的NSView:0x60000013fb80]&gt;中,
    &所述; NSLayoutConstraint:0x60000029dc90的NSView:0x60000013fb80.height&GT = 0.3 *的NSView:0x600000320b40.height&gt;中,
    &所述; NSAutoresizingMaskLayoutConstraint:0x608000288b60 H = - &放大器; V = - &放大器;五:[的NSView:0x60000013e500(360)]&gt;中,
    &LT; NSLayoutConstraint:0x60000029dba0五:| - (0) - 的NSView:0x600000320b40](名称:'|':一个NSView:0x60000013e500)&gt;中,
    &所述; NSLayoutConstraint:0x60000029d1a0五:[的NSView:0x600000320f00(275)]&gt;中,
    &LT; NSLayoutConstraint:0x60000029d420五:[的NSView:0x600000320f00] - (0) - |(名称:'|':一个NSView:0x600000320b40)&gt;中,
    &所述; NSLayoutConstraint:0x60000029d510五:[的NSView:0x600000320dc0] - (0) - [的NSView:0x600000320f00]&gt;中,
    &LT; NSLayoutConstraint:0x60000029d330五:| - (0) - 的NSView:0x600000320dc0](名称:'|':一个NSView:0x600000320b40)&gt;中,
    &LT; NSLayoutConstraint:0x60000029d060五:[NSButton:0x6000001569a0'Search'] - (4) - |(名称:'|':一个NSView:0x600000320dc0)&gt;中,
    &LT; NSLayoutConstraint:0x60000029d0b0五:| - (5) - [NSButton:0x6000001569a0'Search(名称:'|':一个NSView:0x600000320dc0)&gt;中
)将试图打破约束恢复
&所述; NSLayoutConstraint:0x60000029d060五:[NSButton:0x6000001569a0'Search'] - (4) - | (名称:'|':一个NSView:0x600000320dc0)&GT;2014年4月26日09:38:27.770的MyApp [2531:303]无法同时满足约束条件:

    &LT; NSLayoutConstraint:0x60000029dc40五:[的NSView:0x60000013fb80] - (0) - |(名称:'|':一个NSView:0x60000013e500)&gt;中,
    &所述; NSLayoutConstraint:0x60000029dbf0五:[的NSView:0x600000320b40] - (0) - [的NSView:0x60000013fb80]&gt;中,
    &所述; NSLayoutConstraint:0x60000029dc90的NSView:0x60000013fb80.height&GT = 0.3 *的NSView:0x600000320b40.height&gt;中,
    &所述; NSAutoresizingMaskLayoutConstraint:0x608000288b60 H = - &放大器; V = - &放大器;五:[的NSView:0x60000013e500(360)]&gt;中,
    &LT; NSLayoutConstraint:0x60000029dba0五:| - (0) - 的NSView:0x600000320b40](名称:'|':一个NSView:0x60000013e500)&gt;中,
    &所述; NSLayoutConstraint:0x60000029d1a0五:[的NSView:0x600000320f00(275)]&gt;中,
    &LT; NSLayoutConstraint:0x60000029d420五:[的NSView:0x600000320f00] - (0) - |(名称:'|':一个NSView:0x600000320b40)&gt;中,
    &所述; NSLayoutConstraint:0x60000029d510五:[的NSView:0x600000320dc0] - (0) - [的NSView:0x600000320f00]&gt;中,
    &LT; NSLayoutConstraint:0x60000029d330五:| - (0) - 的NSView:0x600000320dc0](名称:'|':一个NSView:0x600000320b40)&gt;中,
    &LT; NSLayoutConstraint:0x60000029d100五:| - (4) - [NSButton:0x6000001564d0](名称:'|':一个NSView:0x600000320dc0)&gt;中,
    &LT; NSLayoutConstraint:0x60000029d150五:[NSButton:0x6000001564d0] - (5) - |(名称:'|':一个NSView:0x600000320dc0)&gt;中
)将试图打破约束恢复
&所述; NSLayoutConstraint:0x60000029d150五:[NSButton:0x6000001564d0] - (5) - | (名称:'|':一个NSView:0x600000320dc0)&GT;2014年4月26日09:38:27.775的MyApp [2531:303]无法同时满足约束条件:

    &LT; NSLayoutConstraint:0x60000029cf70五:[的NSTextField:0x600000198940] - (4) - |(名称:'|':一个NSView:0x600000320dc0)&gt;中,
    &LT; NSLayoutConstraint:0x60000029cfc0五:| - (4) - 的NSTextField:0x600000198940](名称:'|':一个NSView:0x600000320dc0)&gt;中,
    &LT; NSLayoutConstraint:0x60000029dc40五:[的NSView:0x60000013fb80] - (0) - |(名称:'|':一个NSView:0x60000013e500)&gt;中,
    &所述; NSLayoutConstraint:0x60000029dbf0五:[的NSView:0x600000320b40] - (0) - [的NSView:0x60000013fb80]&gt;中,
    &所述; NSLayoutConstraint:0x60000029dc90的NSView:0x60000013fb80.height&GT = 0.3 *的NSView:0x600000320b40.height&gt;中,
    &所述; NSAutoresizingMaskLayoutConstraint:0x608000288b60 H = - &放大器; V = - &放大器;五:[的NSView:0x60000013e500(360)]&gt;中,
    &LT; NSLayoutConstraint:0x60000029dba0五:| - (0) - 的NSView:0x600000320b40](名称:'|':一个NSView:0x60000013e500)&gt;中,
    &所述; NSLayoutConstraint:0x60000029d1a0五:[的NSView:0x600000320f00(275)]&gt;中,
    &LT; NSLayoutConstraint:0x60000029d420五:[的NSView:0x600000320f00] - (0) - |(名称:'|':一个NSView:0x600000320b40)&gt;中,
    &所述; NSLayoutConstraint:0x60000029d510五:[的NSView:0x600000320dc0] - (0) - [的NSView:0x600000320f00]&gt;中,
    &LT; NSLayoutConstraint:0x60000029d330五:| - (0) - 的NSView:0x600000320dc0](名称:'|':一个NSView:0x600000320b40)&gt;中
)将试图打破约束恢复
&所述; NSLayoutConstraint:0x60000029cf70五:[的NSTextField:0x600000198940] - (4) - | (名称:'|':一个NSView:0x600000320dc0)&GT;


解决方案

您必须告知父视图,该视图内将调整。我的方法是看predicate增长,其委托收缩:

   - (无效)ruleEditorRowsDidChange:(NSNotification *)通知{  NSInteger的newRowCount = [_ predicateEditor numberOfRows]。
  NSInteger的的rowHeight = [_ predicateEditor的rowHeight]。  //发送通知 - 大小的变化
  的NSRect newFrame = self.view.frame;
  newFrame.size.height = 30 + newRowCount * rowHeight的;
  [NSNotificationCenter defaultCenter] postNotificationName:@RowsDidChange的对象:[NSValue valueWithRect:newFrame]];
  [_heightConstraint动画] setConstant:rowHeight时* newRowCount]。
}

和父的ViewController一个观察员看大小的变化:

  [NSNotificationCenter defaultCenter] addObserverForName:@RowsDidChange
    对象:无
    队列:无
    usingBlock:^(NSNotification *通知){
        NSValue *值=(NSValue *)notification.object;
        的NSRect rectValue = [值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;        //新的高度设置为mainViewController
        [self.mainViewController观点】SETFRAME:newContentRect];
}];

您不需要发送通知,还可以寄一些委托方法给你父母的ViewController。

祝你好运。

I have some issues with Cocoa Autolayout. I have a window and I add (programmatically) a NSTableView (with its NSScrollView). Until now everything is ok. I can resize my window and the table resizes correctly. This is the code I used.

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

Now.. I want to add (and remove) at runtime another view which is placed at the top of the table. The view is a NSPredicateEditor with its NSScrollView. To be clear: I'm trying to achieve the same behaviour of the Finder when you type something in the search field and the view with the possible search options appears in the main window.

I handle this in this way:

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

I would like that at least one line of the predicate (25 points) are visible. When the user presses the plus button, then more views start to appears (and the scrollview should adapt its size). After some rows (I decided 9) the scrollbars should start to appear and the main view in the window should stop shrinking.

The problem is that when I insert the filter view, it is of almost zero size (like 1 point). Or if I add a minimum size of 25 points, the view is visible but adding rows only increases the ''inner size'' of the scrollview, so scrollbar appears (but the scrollview does not grow and does not make the list view shrink).

I hope I explained correctly the problem.

EDIT:

Taking inspiration from the answer I implemented the delegate:

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

where self.predicateEditorHeight is an IBOutlet to a constraint on the height of the NSScrollView. Then in the enclosing NSWindowController, when I add the predicate editor view I also add a constraint on the proportions of the NSTableView with respect to the predicate view. In this way (because I set it to 0.3) the scroll view can grow until a certain point, and then, after that, it must use its scrollbars.

I still have some issues on the constraints: For example, when I add too many rows in the editor I get

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 )>

解决方案

You have to 'inform' the parent view, that the inner view will resize. My approach was to watch predicate grow and shrink by its delegate:

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

And a 'observer' in the parent ViewController to watch the size changes:

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

You don't need to send a notification, you can also send some delegate method to you parent viewcontroller.

Good luck.

这篇关于可可自动布局:插入(和删除)在运行时编程观点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆