嵌套NSSplitView
个实例会导致奇怪的行为。拖动嵌套的splitView拆分器时,可以移动父splitView的拆分器以容纳更大的子项作为拖动的副作用。
这是一个重现此问题的极简主义项目的URL。只需将最右侧的分离器向右拖动,直到最左侧的分离器开始自行移动。 http://filebin.ca/20ymCpNmtts7/NestedSplitTest.zip
根据我的理解,问题的原因是当拖动splitView的拆分器时,会添加一个新约束,将拖动拆分器左侧的contentView的右边缘绑定到{{1}的左边缘。本身。拖动完成后,将删除此约束。当拖动正在进行并且拆分器受到其他面板的最小宽度的约束时,此临时约束的常量值的总和超过窗格可以调整大小的宽度,这使得NSSplitView本身变大,这反过来又调整了大小最外面的分离器。
我尝试使用NSSplitView
约束分割位置,但是由于临时约束,NSSplitView已经增长后调用此委托方法。实现NSSplitViewDelegate
或constrainMinCoordinate
委托方法之一会使constrainMaxCoordinate
完全忽略面板上配置的最小宽度。
此外,当拖动开始或结束时,无论是通过通知还是通过子类化NSSplitView
,我似乎无法获得正确的事件。对这两个事件都有一个钩子可以让我添加一个临时约束来确保NSSplitView不能向外扩展。即使覆盖NSSplitView
和mouseDown:
也无法正常工作,因为拖动结束后mouseUp:
永远不会被调用。
更新1:
我找到了mouseUp:
未被调用的原因的解释:这是因为使用在mouseUp:
中运行的嵌套RunLoop实现了拆分器的拖动。这就是NSEventTrackingRunLoopMode
和mouseDragged:
事件被静默吞噬的方式。以下是相关文档:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html#//apple_ref/doc/uid/10000060i-CH6-SW4
答案 0 :(得分:1)
了解未调用mouseUp:
的原因是实现此问题的解决方案的关键。这是一个自定义的NSSplitView子类,可以在拖动拆分器时阻止splitView向外扩展。
@interface NestableSplitView : NSSplitView
@property(strong) NSLayoutConstraint* temporaryWidthConstraint;
@end
@implementation NestableSplitView
- (void)mouseDown:(NSEvent *)theEvent
{
if (!self.temporaryWidthConstraint) {
self.temporaryWidthConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:0];
}
self.temporaryWidthConstraint.constant = NSWidth(self.bounds);
[self addConstraint:self.temporaryWidthConstraint];
[super mouseDown:theEvent]; // This call is blocking until the drag is finished
[self removeConstraint:self.temporaryWidthConstraint];
}
@end