NSSplitView和自动布局(NSSplitView and autolayout)

2019-07-30 04:05发布

我应该如何使用自动布局限制内NSSplitView子视图?

NSSplitView子视图有3子视图: topPanetableContainerbottomPane和我这样设置约束:

NSDictionary* views = NSDictionaryOfVariableBindings(topPane, tableContainer, bottomPane);

for (NSView* view in [views allValues]) {
    [view setTranslatesAutoresizingMaskIntoConstraints:NO];
}

[myView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[topPane(34)][tableContainer][bottomPane(24)]|"
                                                               options:0 
                                                               metrics:nil 
                                                                 views:views]];

[mySplitView addSubview:myView];

而在控制台得到这个:

Unable to simultaneously satisfy constraints:
(
    "<NSLayoutConstraint:0x7fd6c4b1f770 V:[NSScrollView:0x7fd6c4b234c0]-(0)-[CPane:0x7fd6c4b2fd10]>",
    "<NSLayoutConstraint:0x7fd6c4b30910 V:[CPane:0x7fd6c4b2f870(34)]>",
    "<NSLayoutConstraint:0x7fd6c4b30770 V:|-(0)-[CPane:0x7fd6c4b2f870]   (Names: '|':NSView:0x7fd6c4b22e50 )>",
    "<NSLayoutConstraint:0x7fd6c4b212f0 V:[CPane:0x7fd6c4b2fd10]-(0)-|   (Names: '|':NSView:0x7fd6c4b22e50 )>",
    "<NSLayoutConstraint:0x7fd6c4b2f910 V:[CPane:0x7fd6c4b2f870]-(0)-[NSScrollView:0x7fd6c4b234c0]>",
    "<NSLayoutConstraint:0x7fd6c4b21290 V:[CPane:0x7fd6c4b2fd10(24)]>",
    "<NSAutoresizingMaskLayoutConstraint:0x7fd6c3630430 h=--& v=--& V:[NSView:0x7fd6c4b22e50(0)]>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7fd6c4b1f770 V:[NSScrollView:0x7fd6c4b234c0]-(0)-[CPane:0x7fd6c4b2fd10]>

我认为<NSAutoresizingMaskLayoutConstraint:0x7fd6c3630430 h=--& v=--& V:[NSView:0x7fd6c4b22e50(0)]>导致此,但我不能复位自动调整掩模,因为NSSplitView设置它。

什么是使用拆分视图内自动布局最好的方法? 而有什么办法没有处理与自动布局拆分视图子视图的最小/最大尺寸NSSplitViewDelegate

Answer 1:

我发现,如果我在任何的这个委托方法我的窗口和控制拆分视图具有工具栏出现此错误:

splitView:constrainMinCoordinate:ofSubviewAt:   
splitView:constrainMaxCoordinate:ofSubviewAt:
splitView:shouldAdjustSizeOfSubview:

溶液在windowDidLoad安装工具栏窗口中。



Answer 2:

NSSplitView已经从一开始一个奇怪的东西,如果它很快就会消失它不会让我感到吃惊。 试图让NSSplitView与自动版式工作了一个月了,并从一个绝望的攻击,以另一下沉后,我终于放弃了。

我的解决办法是在所有自动版式不使用NSSplitView。 因此,无论NSSplitView没有自动布局或自动布局不NSSplitView:只是躺在你的子视图彼此相邻并添加:因为它的声音,这不是那么复杂NSLayoutConstraints作为IBOutlets 。 这些约束的常量然后可以设置并从代码控制器改变。 有了这种方法,您可以设置原点(负偏移使其滑出窗口),宽度和关系到其他子视图-加上它真的很容易动画与视图的动画约束(曾经试图动画一NSSplitView?)

唯一缺少的是对分隔鼠标拖拽,但可以用几行代码来实现,在自定义“SPLITVIEW”跟踪mouseEvents。

有苹果(可惜只有垂直)的自动版式“SPLITVIEW”例如,我已经看到在github上至少一个新项目最近。 虽然对我来说,我想那会更容易与我的应用程序的特定需要我的自定义解决方案重新开始,而不是试图创造一些非常普遍的(从而使它过于复杂处理)。

编辑:我现在完成了从单独的笔尖加载其子视图我的自定义SPLITVIEW。 没有约束的问题,没有自动布局警告。 相比于试图让它与NSSplitView工作整整一个月,我现在有根据的限制,很容易动画,只在一个晚上创建工作自SPLITVIEW。 我肯定会推荐这个选择!



Answer 3:

10.8固定的问题,看它的发行说明。

这里是我的10.7溶液(自定义拆分视图): https://github.com/benuri/HASplitView.git



Answer 4:

对于任何人谁在未来绊倒这一点,并正在寻找一个快速启动到基于约束的NSSplitView替代品,我这里写一个小项目试图重建的一部分NSSplitView使用自动布局的特点:

https://github.com/jwilling/JWSplitView

这有点马车,但它可能是任何人想要走这条路了有益的参考。



Answer 5:

你不想禁用translatesAutoresizingMaskIntoConstraints可言。 你不应该乱用系统的观点限制。 NSSplitView处理针对个人观点本身的大小和你基本上是试图撕开它的控制了。 更何况,你忘了占分离器。

设定(对于这个问题或恒定)最小或最大宽度/高度上的SPLITVIEW正确的方法是单独设置的那些东西上的意见。 特别是,如果你在代码中这样做,你将需要使用constraintsWithVisualFormat 2个独立的电话,否则视觉格式的语言将创建视图之间的约束。

你可以做到这一切在IB就好了。 你甚至可以设置在拆分视图每个视图,这将导致一个或另一个视图时,窗口没有,而不是平均分配的调整大小来调整的优先级。



Answer 6:

虽然我讨厌不同意,但AUCO的回答should't进行表决最高。 这是不以任何方式与工作足够量的解决问题有帮助。 在我看来,NSSplitView只是以往那些谁没有阅读文档不够好问题。

这里提到的问题,实际的解决方案是非常简单的:自动布局介绍NSSplitView新的“保持优先级API”。 而作为文档说:设置较低的值,以一个子视图的保持优先级,会让他更有可能较早采取的宽度。 所有这一切都可以在IB和编程设置,没有任何绝望。 工作的量需要20秒左右。



Answer 7:

我加载所有由笔尖文件和setTranslatesAutoresizingMaskIntoConstraints:NO之后。

因此,也许你应该先通过添加[mySplitView addSubview:myView]; 您的意见和禁用事后自动调整大小面具约束的翻译和在此之后您将contraint添加到myView

编辑:

好吧,看来我missunderstand的MyView的。 你必须约束添加到子视图,而不是到SPLITVIEW。

[topPane addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topPane(34)]" options:0 metrics:nil views:views]];

[bottomPane addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[bottomPane(24)]" options:0 metrics:nil views:views]];

你不必加边缘约束(以下简称“|”,在“V:| [topPane(34)]”),因为在子视图NSSplitView已经自动调整。

这导致此例如用于topPane约束:

注:忽略子视图的内容,他们只是占位符



Answer 8:

我花了一些时间让我自动布局干净的警告,但我没有得到它的IB(几个splitviews和子视图)来处理。

我的布局是这样的:

RootView
| - 第一NSSplitView(3个纵子视图)
| ----的UIView(左)
| ---- 第二NSSplitView(中心与2个水平子视图)
| --- UIView的(上)
| --- 第三NSSplitView(底部和3个垂直子视图)
| ---的UIView(左)
| ---的UIView(中心)
| ---的UIView(右)
| ----的UIView(右)

我的问题是,我有我的所有子视图19个警告,但我的布局显得精致而工作应该如何。 过了一会儿,我发现我的警告的原因:在我的第一SPLITVIEW外意见的约束。

两个视图(左和右)有一个宽度约束用“宽度> = 200”,并且中心视图(第二SPLITVIEW)无约束(因为它的最小宽度和最大宽度,其中通过它的子视图的处理)。

这些警告给我看,自动布局要缩小我的IB-UI-布局,因为计算,其中比我小的布局最小宽度,但我didn't要缩小它的IB。

我添加了一个固定的约束“宽度= 200”两者我的第一SPLITVIEW的外子视图并检查“在构建时去掉”。

现在我的布局是免费的警告和一切工作就应该是这样。

我的结论

我想用自动版式和splitviews问题是,自动布局无法处理子视图的宽度限制。 我们要使用splitviews的原因是,我们要的意见动态宽度,我们希望它在两个方向上,收缩和expans。

所以没有宽度<= XXX &&宽度> = XXX。 自动布局只能处理它的一个,我们在IB得到警告。 您可以在IB的临时限制,这将在运行之前删除解决这个问题。

我希望这是有道理的我写的,但它在我的项目运行良好。

PS:我无法找到任何解决办法,直到今天,我发现这个线程..所以我猜你的帖子启发了我:-)



Answer 9:

我用这个类作为一种变通方法,它并不完美(子视图口吃位),但它畅通了我。 我使用这个类,因为每个拆分视图窗格中的自定义类。

@interface FBSplitPaneView : NSView

@end

@implementation FBSplitPaneView

- (void)setFrame:(NSRect)frame
{
  for (NSView *subview in self.subviews) {
    subview.frame = self.bounds;
  }
  [super setFrame:frame];
}

@end


文章来源: NSSplitView and autolayout