1

I have a transparent .png image that lays over an NSView and it should look like this:

enter image description here

However, sometimes, with no rhyme or reason or indication that it is going to do this, the NSImageView falls behind the NSView:

enter image description here

I am not sure how to keep the NSImageView above the NSView, or why it even falls behind the NSView.

Here is what it looks like in Interface Builder: enter image description here

Update:

I have tried the following with same results:

[header removeFromSuperview];
[mainView addSubview:header positioned:NSWindowAbove relativeTo:nil];

What is a better way to achieve this effect?

WrightsCS
  • 50,551
  • 22
  • 134
  • 186

3 Answers3

2

Cocoa UI elements that overlap have an undefined drawing order, and Apple states that you shouldn't overlap them. You could create some custom drawing code to make your current design work. However, honestly I would change the design so it matches with Mac OS X's human interface guidelines. You can read about these at the link below. http://developer.apple.com/library/mac/#documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGIntro/XHIGIntro.html%23//apple_ref/doc/uid/TP30000894-TP6

Skyler Saleh
  • 3,961
  • 1
  • 22
  • 35
  • Still doesnt explain why the front view falls behind. – WrightsCS Feb 13 '11 at 09:14
  • Apple does not have a specified drawing order for elements as Cocoa is inherently 2d. http://lists.apple.com/archives/cocoa-dev/2006/Apr/msg02307.html However having a subview that exceeds the bounds of the parent view also results in undefined behavior. – Skyler Saleh Feb 13 '11 at 17:03
2

When you have two overlapping NSView on the same level it is undefined what the drawing order will be. You can sort the drawing of the subviews using SubviewsUsingFunction:context:. You'll have to provide a comparison function that compares based on some value (e.g. tag):

NSComparisonResult viewCompareByTag(NSView *firstView, NSView *secondView, void *context) {
    return ([firstView tag] > [secondView tag]) ? NSOrderedAscending : NSOrderedDescending;
}

[mySuperView sortSubviewsUsingFunction:&viewCompareByTag context:nil];
WrightsCS
  • 50,551
  • 22
  • 134
  • 186
diederikh
  • 25,221
  • 5
  • 36
  • 49
  • So you called `[mainView sortSubviewsUsingFunction:&viewCompareByTag context:nil]` and you gave the views a tag like '0' and '1' and the ordering is still going wrong? Are you sure the two views are mainView's subviews? – diederikh Feb 13 '11 at 10:24
2

Turns out that I had to re-arrange some of the views in Interface Builder, then in code:

[[header layer] setZPosition:1.0f];
WrightsCS
  • 50,551
  • 22
  • 134
  • 186
  • I had a similar problem when doing a view-swapping transitional effect which required temporarily overlapping views. The superimposed CALayer/sublayer animation was playing behind the other views. @RTS's post made it clear what was going on. And calling setZPosition to 1 on the root layer solved it. Many thanks to both of you. – Wienke Apr 19 '11 at 06:23
  • (P.S. It turned out zPosition could be used to bring sublayers in front of child views, so I was able to dispense with the superimposed imageview and avoid Apple’s wrath altogether.) – Wienke Apr 20 '11 at 15:15