有没有适当的方法来处理这种重叠? NSView B始终会“盖住”NSView A,因此我想要NSView A被覆盖的部分被掩盖。
Chris,唯一的解决方案是使用CALayers。这绝对是唯一的解决方案。
在OSX中,NSViews存在严重问题(2010年9月):兄弟节点无法正常工作。其中一个或另一个将随机出现在顶部。
再次强调,问题出在兄弟节点上。
测试方法:使用NSViews和/或nsimageviews。创建一个视图,其中包含一个大图像(比如1000x1000)。在视图中,放置三到四个小图像/NSViews。然后在顶部放置另一个大的1000x1000图像。反复构建和启动应用程序-你会发现它是明显有问题的。通常,下面(小)层会出现在覆盖层的顶部。如果在NSViews上开启layer-backing,无论尝试什么组合都没有帮助。所以这就是明确的测试。
您必须放弃NSViews并使用CALayers。
唯一让人烦恼的是,您无法使用IB设置您的内容。您必须在代码中设置所有层位置。
yy = [CALayer layer];
yy.frame = CGRectMake(300,300, 300,300);
rear = [CALayer layer];
rear.backgroundColor = CGColorCreateGenericRGB( 0.75, 0.75, 0.75, 1.0 );
[yourOnlyNsView setLayer:rear]; // these two lines must be in this order
[yourOnlyNsView setWantsLayer:YES]; // these two lines must be in this order
[rear addSublayer:rr];
[rear addSublayer:yy];
[yy addSublayer:s1];
[yy addSublayer:s2];
[yy addSublayer:s3];
[yy addSublayer:s4];
[rear addSublayer:tt];
[rear addSublayer:ff];
一切都完美地运作,您可以嵌套和分组任何内容,并且所有内容都能够无缝地与其它元素正确地出现在上/下方,不管您的结构有多么复杂。稍后您可以对层进行任何操作或以典型方式重新排列物品。
-(void) shuff
{
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithFloat:0.0f]
forKey:kCATransactionAnimationDuration];
if ..
[rear insertSublayer:ff below:yy];
else
[rear insertSublayer:ff above:yy];
[CATransaction commit];
}
每次执行操作时,烦人的“在零秒内”包装器唯一存在的原因是为了防止免费提供给您的动画效果-除非您需要动画效果!
顺便说一下,在苹果公司的以下引用中:
出于性能原因,Cocoa不会在同级视图之间强制裁剪,也不保证当同级视图重叠时正确地使其无效和绘制。
他们接下来的句子...
如果您想要将一个视图绘制在另一个视图的前面,则应将前置视图设置为后置视图的子视图(或后代)。
在很大程度上是毫无意义的(您不能总是用子视图替换同级视图;并且在上述测试中描述的明显错误仍然存在)。
所以这就是CALayers!享受吧!
有一种方法可以在不使用 CALayers
的情况下实现,而我正在开发的一个应用程序可以证明这一点。创建两个窗口并使用以下代码:
[mainWindow addChildWindow:otherWindow ordered:NSWindowAbove];
[mainWindow removeChildWindow:otherWindow];
[otherWindow orderOut:nil];
您可能希望一并获取窗口的标题栏:
[otherWindow setStyleMask:NSBorderlessWindowMask];
self.addSubview(btn2, positioned: NSWindowOrderingMode.Above, relativeTo: btn1)
然而,只要你通过"needDisplay = true"调用任何一个视图来重绘自己,视图的顺序就不会被尊重。
兄弟视图将不会收到drawRect调用,只有视图的直接层次结构会。
为了解决这个问题,我必须深入挖掘。可能需要一周的研究,并且我将我的发现分散在几篇文章中。最终突破在这篇文章中:http://eon.codes/blog/2015/12/24/The-odd-case-of-luck/
但请注意,这个概念很难理解,但它非常有效。这里是最终结果和支持它的代码,以及指向Github存储库等的链接:http://eon.codes/blog/2015/12/30/Graphic-framework-for-OSX/
NSView B
始终覆盖在NSView A
之上,添加subview:
时,请确保使用正确的NSWindowOrderingMode
。[parentView addSubview:B positioned:NSWindowAbove relativeTo:A];
你还需要记住,如果视图B是100%不透明的,那么A的隐藏部分将不会被要求重新绘制。
如果你正在移动子视图,你还需要确保调用-setNeedsDisplayInRect:
来揭示视图中的区域。
addSubview:positioned:relativeTo
和sortSubviewsUsingFunction:context
有什么意义呢?前者的文档说明如下:“将视图插入接收器的子视图中,以便它立即显示在另一个视图的上方或下方。”如果Cocoa在绘制时没有强制执行排序,那么排序子视图有什么意义呢?事件处理? - kennyc