Change NSView subviews order
Asked Answered
D

4

8

I'm working at a custom control that presents different handles. I want to be sure that the selected handle has a Z-index grater then the others handles.

Is there a way to swap view order? I found this function sortSubviewsUsingFunction:context: but i can't understand whether this is the right solution.

Disagreeable answered 3/7, 2012 at 13:9 Comment(1)
you can loop through all subviews and get them and you can insert every one atindex on the view...Matronna
D
7

Cocoa introduced a new API in macOS 10.0.
It's similar to iOS, you can pass another view to be displayed below or above.

[self.view addSubview:myView positioned:NSWindowBelow relativeTo:myViewInBackground];

Checkout the documentation; in my experience NSWindowBelow and NSWindowAbove seemed reversed though.

Dactylogram answered 9/8, 2015 at 7:21 Comment(3)
Wouldn't you need to use the child.removeFromSuperview() before parent.addSubview(child,index) to swap? And wouldn't it then be more appropriate to use the sortSubviewsUsingFunction which is in the NSView class?Issus
After some testing. Just adding the view again works well. No need to remove.Issus
The Docs say it has been there since 10.0 not 10.10. So also usable with targets below 10.10.Induplicate
I
6

It is pretty simple, you can use a function that compare 2 subviews to reorder them. Here a simple solution based on view's tag:

[mainView sortSubviewsUsingFunction:(NSComparisonResult (*)(id, id, void*))compareViews context:nil];

...

NSComparisonResult compareViews(id firstView, id secondView, void *context) { 
    int firstTag = [firstView tag];
    int secondTag = [secondView tag];

    if (firstTag == secondTag) {
        return NSOrderedSame;
    } else {
        if (firstTag < secondTag) {
            return NSOrderedAscending;
        } else { 
            return NSOrderedDescending;
        }
    }
}
Instinct answered 3/7, 2012 at 13:20 Comment(2)
I'm sorry but I can't understand the prototype of the compareViews function. Does it use a mix of Objective-c and C?Disagreeable
Objective-C is a superset of C hence this is Objective-CLibrary
G
-4

Yes, sortSubviewsUsingFunction:context: can do what you're looking to do, however it might be overkill if all you'd like is for one particular view to sit on top of the (unordered) others. In that case, you should look into the bringSubviewToFront: method of UIView. That way, you could do something like this in your IBAction for bringing up the handle:

[self.view bringSubviewToFront: handle];

Assuming that handle is an object that is/inherits from UIView. If this isn't what you're looking for, then by all means, go with sortSubviewsUsingFunction:context:, in which case you'll need to alter the individual tag properties for each subview, and sort accordingly.

Gayla answered 3/7, 2012 at 13:19 Comment(5)
I'm working on OSX non iOS... but +1 because I can search for similar functions.Disagreeable
Ah, in that case, this looks a little hackish, but you could always add a category to do the following: #4236804Gayla
Thank you, I need to understand if this solution, in terms of performance, is better then the sortSubviewsUsingFunctionDisagreeable
No problem! I can't say authoritatively that it would be faster, but my thought would be a solid yes. This hinges on the internals of sortSubviewUsingFunction:context:, which I can't comment on. I imagine, however, that it works something like this: 1) manipulate the internal array of subview pointers, then 2) repaint the UI. Certainly ours will be faster for step 1, given that it doesn't iterate through all the subviews like the sort would. For step 2, it's probably either faster or equal, in that the implementation will either repaint all (ours is faster) or repaint just the change (equal).Gayla
That said, you might want to benchmark the different approaches if performance is really critical to your app - take a look at #3018388Gayla
M
-6

As i understand from you question you can loop all you view and add them to array then you have the option to add them to you view with index .. and you have the following functions.

[self.view insertSubview:view1 atIndex:2]
[self.view insertSubview:view1 aboveSubview:0]
[self.view insertSubview:view1 belowSubview:1]

then you can swap it's order as you need..

Matronna answered 3/7, 2012 at 13:18 Comment(1)
Looks like the OP was asking about NSViews this is only for UIViewsKela

© 2022 - 2024 — McMap. All rights reserved.