移动嵌套NSSplitView的拆分器使其向外扩展

时间:2015-05-08 04:20:06

标签: macos cocoa autolayout nssplitview

嵌套NSSplitView个实例会导致奇怪的行为。拖动嵌套的splitView拆分器时,可以移动父splitView的拆分器以容纳更大的子项作为拖动的副作用。

这是一个重现此问题的极简主义项目的URL。只需将最右侧的分离器向右拖动,直到最左侧的分离器开始自行移动。 http://filebin.ca/20ymCpNmtts7/NestedSplitTest.zip

根据我的理解,问题的原因是当拖动splitView的拆分器时,会添加一个新约束,将拖动拆分器左侧的contentView的右边缘绑定到{{1}的左边缘。本身。拖动完成后,将删除此约束。当拖动正在进行并且拆分器受到其他面板的最小宽度的约束时,此临时约束的常量值的总和超过窗格可以调整大小的宽度,这使得NSSplitView本身变大,这反过来又调整了大小最外面的分离器。

我尝试使用NSSplitView约束分割位置,但是由于临时约束,NSSplitView已经增长后调用此委托方法。实现NSSplitViewDelegateconstrainMinCoordinate委托方法之一会使constrainMaxCoordinate完全忽略面板上配置的最小宽度。

此外,当拖动开始或结束时,无论是通过通知还是通过子类化NSSplitView,我似乎无法获得正确的事件。对这两个事件都有一个钩子可以让我添加一个临时约束来确保NSSplitView不能向外扩展。即使覆盖NSSplitViewmouseDown:也无法正常工作,因为拖动结束后mouseUp:永远不会被调用。

更新1: 我找到了mouseUp:未被调用的原因的解释:这是因为使用在mouseUp:中运行的嵌套RunLoop实现了拆分器的拖动。这就是NSEventTrackingRunLoopModemouseDragged:事件被静默吞噬的方式。以下是相关文档:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html#//apple_ref/doc/uid/10000060i-CH6-SW4

1 个答案:

答案 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