2015-05-08 42 views
0

嵌套NSSplitView實例會導致奇怪的行爲。拖動嵌套的splitView的拆分器時,可以移動父級splitView的拆分器以容納較大的子元素作爲拖動的副作用。移動嵌套NSSplitView的分離器使其向外生長

這是一個極簡主義項目的網址,它重現了這個問題。只需將最右邊的分離器拖向右邊,直到最左邊的分離器開始自行移動。 http://filebin.ca/20ymCpNmtts7/NestedSplitTest.zip

據我的理解,問題的原因是,當拖動splitView的拆分器時,會添加一個新約束,將被拖動拆分器左側的contentView的右邊緣綁定到NSSplitView本身的左邊緣。拖動完成後,此約束將被刪除。當拖動正在進行,並且分離器受到其他面板的最小寬度的限制時,則此臨時約束的常量值的總和超出了窗格可以調整的寬度,並且這會使NSSplitView本身變大,進而調整最外面的分離器。

我已經嘗試使用NSSplitViewDelegate約束分割位置,但是在NSSplitView已經由於臨時約束而增長之後調用此委託方法。實施constrainMinCoordinateconstrainMaxCoordinate委託方法之一會使NSSplitView完全忽略面板上配置的最小寬度。

此外,我似乎無法通過通知或子類NSSplitView拖動開始或結束時得到適當的事件。在這兩個事件上掛鉤會讓我添加一個臨時約束,以確保NSSplitView不能向外擴展。即使壓倒性的mouseDown:mouseUp:也不起作用,因爲mouseUp:在拖動結束後從未被調用過。

更新1: 我已經找到了原因mouseUp:的解釋是不是叫:這是因爲分離器的拖拽使用在NSEventTrackingRunLoopMode運行嵌套RunLoop實現。這就是mouseDragged:mouseUp:事件如何被無聲地吞噬。以下是相關文檔:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/HandlingMouseEvents/HandlingMouseEvents.html#//apple_ref/doc/uid/10000060i-CH6-SW4

回答

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