278

I want to move one view on top of another, how can I know the z index of the view, and how to move on to top?

0

9 Answers 9

347

You can use the zPosition property of the view's layer (it's a CALayer object) to change the z-index of the view.

theView.layer.zPosition = 1;

As Viktor Nordling added, "big values are on top. You can use any values you want, including negative values." The default value is 0.

You need to import the QuartzCore framework to access the layer. Just add this line of code at the top of your implementation file.

#import "QuartzCore/QuartzCore.h"
8
  • 10
    Just as a helper, big values are "on top". You can use any values you want, including negative values. Commented Jun 9, 2012 at 13:08
  • 14
    This solution is better in case you want your view to be always on top. Just set zPosition to MAXFLOAT Commented Nov 22, 2012 at 17:42
  • 36
    I've just learned that the zPosition of the layer, and the UIView's input handler, are on two different Z-orders. It's really odd when your clicks "pass through"
    – Stephen J
    Commented Dec 11, 2012 at 22:07
  • does the views' superview have to be the same in order to make zPosition works?
    – Hlung
    Commented Sep 15, 2013 at 17:15
  • 4
    I noticed that, even though the view is on top, clicks go through it to objects underneath. This ought to be considered a bug. I am trying to find a general way to avoid that problem, without having to explicitly disable user interactions of any views that happen to be underneath. Commented Aug 12, 2015 at 15:02
287

UIView siblings are stacked in the order in which they are added to their superview. The UIView hierarchy methods and properties are there to manage view order. In UIView.h:

@property(nonatomic,readonly) UIView *superview;
@property(nonatomic,readonly,copy) NSArray *subviews;

- (void)removeFromSuperview;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;

- (void)addSubview:(UIView *)view;
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;

- (void)bringSubviewToFront:(UIView *)view;
- (void)sendSubviewToBack:(UIView *)view;

The sibling views are ordered back to front in the subviews array. So the topmost view will be:

[parentView.subviews lastObject];

and bottom view will be:

[parentView.subviews objectAtIndex:0];

Like Kolin Krewinkel said, [parentView bringSubviewToFront:view] will bring the view to the top, but this is only the case if the views are all siblings in the hierarchy.

130

IB and Swift

Given the flowing layout where yellow is the superview and red, green, and blue are sibling subviews of yellow,

views - red view on top

the goal is to move a subview (let's say green) to the top.

views - green view on top

In Interface Builder

In the Interface Builder all you need to do is drag the view you want showing on the top to the bottom of the list in the Documents Outline.

order of views in Interface Builder

Alternatively, you can select the view and then in the menu go to Editor > Arrange > Send to Front.

In Swift

There are a couple of different ways to do this programmatically.

Method 1

yellowView.bringSubviewToFront(greenView)
  • This method is the programmatic equivalent of the IB answer above.

  • It only works if the subviews are siblings of each other.

  • An array of the subviews is contained in yellowView.subviews. Here, bringSubviewToFront moves the greenView from index 0 to 2. This can be observed with

      print(yellowView.subviews.indexOf(greenView))
    

Method 2

greenView.layer.zPosition = 1
  • This method just moves the 3D position of the layer higher (closer to the user) on the z-axis. Since the default is 0 for all the other views, the result is that the greenView looks like it is on top. However, it still remains at index 0 of the yellowView.subviews array. This can cause some unexpected results, though, because things like tap events will still go first to the view with the highest index number. For that reason, it might be better to go with Method 1 above.
  • The zPosition could be set to CGFloat.greatestFiniteMagnitude (CGFloat(FLT_MAX) in older versions of Swift) to ensure that it is on top.
3
  • thanks for this... i spent 8 hours trying to figure this out. yellowView.bringSubviewToFront(greenView) worked perfectly.
    – MsNichols
    Commented Mar 3, 2016 at 21:45
  • Interestingly, container views do not respect this! You have to manually move them in code, it seems.
    – Fattie
    Commented Jun 8, 2016 at 17:26
  • Thank you for the explanation regarding the difference of moving the actual index or changing the z-index, which seems to be more like a cosmetic change.
    – Yann
    Commented Dec 31, 2020 at 10:16
76
[parentView bringSubviewToFront:view] ;
0
19

If you want to do this through XCode's Interface Builder, you can use the menu options under Editor->Arrangement. There you'll find "Send to Front", "Send to Back", etc.

1
  • 1
    What if the options from Arrange are disabled?
    – mr5
    Commented Feb 12, 2020 at 10:31
9

Within the view you want to bring to the top... (in swift)

superview?.bringSubviewToFront(self)
1
  • btnDOWN.superview?.bringSubview(toFront: btnDOWN)
    – Criss
    Commented Dec 1, 2018 at 16:10
7

We can use zPosition in ios

if we have a view named salonDetailView eg : @IBOutlet weak var salonDetailView: UIView!

In my case see the image

and have UIView for GMSMapView eg : @IBOutlet weak var mapViewUI: GMSMapView!

To show the View salonDetailView upper of the mapViewUI

use zPosition as below

salonDetailView.layer.zPosition = 1
3
  • please post photos and code directly here in your answer, to make it easier for OP to get it. Commented Mar 22, 2019 at 8:03
  • as a beginner, StackOverflow will not allow me to do that sorry. you can check the problem image i.sstatic.net/d9Cx3.png
    – abhijith k
    Commented Mar 22, 2019 at 12:05
  • Worked like a charm on my CAShapeLayers in macos! Commented Jun 21, 2022 at 21:17
4

If you are using cocos2d, you may see an issue with [parentView bringSubviewToFront:view], at least it was not working for me. Instead of bringing the view I wanted to the front, I send the other views back and that did the trick.

[[[CCDirector sharedDirector] view] sendSubviewToBack:((UIButton *) button)]; 
0

Or use this

- (void)insertSubview:(UIView *)view belowSubview:(UIView*)siblingSubview;

as per here

Not the answer you're looking for? Browse other questions tagged or ask your own question.