Macos 移动嵌套NSSplitView的拆分器会使其向外增长
嵌套Macos 移动嵌套NSSplitView的拆分器会使其向外增长,macos,cocoa,autolayout,nssplitview,Macos,Cocoa,Autolayout,Nssplitview,嵌套NSSplitView实例会导致一种奇怪的行为。拖动嵌套splitView的拆分器时,可以移动父splitView的拆分器以容纳较大的子拆分器,这是拖动的副作用 下面是一个复制此问题的极简主义项目的URL。只需向右拖动最右边的拆分器,直到最左边的拆分器开始自行移动 据我所知,问题的原因是,在拖动splitView的拆分器时,添加了一个新的约束,将被拖动拆分器左侧的contentView的右边缘绑定到NSSplitView本身的左边缘。完成拖动后,将删除此约束。当拖动正在进行且拆分器受到其他面
NSSplitView
实例会导致一种奇怪的行为。拖动嵌套splitView的拆分器时,可以移动父splitView的拆分器以容纳较大的子拆分器,这是拖动的副作用
下面是一个复制此问题的极简主义项目的URL。只需向右拖动最右边的拆分器,直到最左边的拆分器开始自行移动
据我所知,问题的原因是,在拖动splitView的拆分器时,添加了一个新的约束,将被拖动拆分器左侧的contentView的右边缘绑定到NSSplitView
本身的左边缘。完成拖动后,将删除此约束。当拖动正在进行且拆分器受到其他面板最小宽度的约束时,此临时约束的常量值的总和超过了窗格可以调整大小的宽度,这会使NSSplitView本身变大,从而调整最外层拆分器的大小
@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
我曾尝试使用NSSplitViewDelegate
约束拆分位置,但由于临时约束,在NSSplitView已经增长之后调用此委托方法。实现一个ConstraintMinCoordinate
或ConstraintMaxCoordinate
委托方法会使NSSplitView
完全忽略面板上配置的最小宽度
此外,当拖动开始或结束时,我似乎无法通过通知或子类化NSSplitView
获得正确的事件。在这两个事件上都有一个钩子将允许我添加一个临时约束,以确保NSSplitView不能向外扩展。即使覆盖mouseDown:
和mouseUp:
也不起作用,因为在拖动结束后,mouseUp:
从未被调用
更新1:
我找到了一个解释,解释了为什么没有调用
mouseUp:
:这是因为拆分器的拖动是使用在nseventtrackingrunloop模式下运行的嵌套RunLoop实现的。这就是mouseDragged:
和mouseUp:
事件被默默吞没的方式。以下是相关文档:了解为什么不调用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