Bringing a subview to be in front of all other views
Asked Answered
R

8

66

I am working on integrating an ad provider into my app currently. I wish to place a fading message in front of the ad when the ad displays but have been completely unsuccessful.

I made a function which adds a subview to my current view and tries to bring it to the front using

[self.view bringSubviewToFront:mySubview]

The function fires on notification that the ad loaded (the notification is from the adprovider's SDK). However, my subview does not end up in front of the ad. I imagine this is made purposely difficult by the ad provider, but I wish to do it regardless. I am currently discussing with the provider whether or not this can be allowed. But for the time being, I just want to see if it's even possible.

Is there anyway I can force a subview of mine to be the top-most view such that it will not be obstructed by anything?

Rubella answered 1/11, 2012 at 17:34 Comment(0)
S
90

What if the ad provider's view is not added to self.view but to something like [UIApplication sharedApplication].keyWindow?

Try something like:

[[UIApplication sharedApplication].keyWindow addSubview:yourSubview]

or

[[UIApplication sharedApplication].keyWindow bringSubviewToFront:yourSubview]
Southing answered 1/11, 2012 at 17:38 Comment(2)
Doesn't work for iAd banner views... which is a common "needs to be on top" problem. (iAds are not allowed in non-VCs)Striated
or [parentview bringSubviewToFront:yourSubview] , where parentview is the inmediate view of the subviewHoseahoseia
N
181

try this:

self.view.layer.zPosition = 1;
Ninth answered 2/4, 2015 at 12:9 Comment(8)
Thank you for this answer. Was useful for a Map pin issue (I wanted to force one on top of the others)Astyanax
Can I ask why you sent this reply 3 years after this question was posted?Rubella
i was searching 3 years after the solution =)Ninth
Unfortunately this can not change the gesture responding order.Thirteen
This only puts the view in front, but not all the gesture and touch events. so when the user tries to touch the view, it will touch some other view. The solution by @jere is the correct one.Hoseahoseia
i was searching 12 years after the solution =)Overpowering
how to make the above view activeTeletypewriter
Well if you do this repeatedly for some arbitrary close by views, they both have zPosition == 1, and that's not ok. (without custom zPosition logic)Moustache
S
90

What if the ad provider's view is not added to self.view but to something like [UIApplication sharedApplication].keyWindow?

Try something like:

[[UIApplication sharedApplication].keyWindow addSubview:yourSubview]

or

[[UIApplication sharedApplication].keyWindow bringSubviewToFront:yourSubview]
Southing answered 1/11, 2012 at 17:38 Comment(2)
Doesn't work for iAd banner views... which is a common "needs to be on top" problem. (iAds are not allowed in non-VCs)Striated
or [parentview bringSubviewToFront:yourSubview] , where parentview is the inmediate view of the subviewHoseahoseia
K
23

Swift 2 version of Jere's answer:

UIApplication.sharedApplication().keyWindow!.bringSubviewToFront(YourViewHere)

Swift 3:

UIApplication.shared.keyWindow!.bringSubview(toFront: YourViewHere)

Swift 4:

UIApplication.shared.keyWindow!.bringSubviewToFront(YourViewHere)

Hope it saves someone 10 seconds! ;)

Kiki answered 26/1, 2016 at 20:3 Comment(1)
What if I want to bring the keyWindow itself to the front ? I am facing an issue where the keyWindow stays on the back for some reason...Thordis
C
18

I had a need for this once. I created a custom UIView class - AlwaysOnTopView.

@interface AlwaysOnTopView : UIView
@end

@implementation AlwaysOnTopView

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (object == self.superview && [keyPath isEqual:@"subviews.@count"]) {
        [self.superview bringSubviewToFront:self];
    }

    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}

- (void)willMoveToSuperview:(UIView *)newSuperview {
    if (self.superview) {
        [self.superview removeObserver:self forKeyPath:@"subviews.@count"];
    }

    [super willMoveToSuperview:newSuperview];
}

- (void)didMoveToSuperview {
    [super didMoveToSuperview];

    if (self.superview) {
        [self.superview addObserver:self forKeyPath:@"subviews.@count" options:0 context:nil];
    }
}

@end

Have your view extend this class. Of course this only ensures a subview is above all of its sibling views.

Croce answered 1/11, 2012 at 17:39 Comment(1)
This is brilliant!Tarentarentum
A
8

As far as i experienced zposition is a best way.

self.view.layer.zPosition = 1;

Arson answered 6/3, 2017 at 13:17 Comment(0)
A
2

Let me make a conclusion. In Swift 5

You can choose to addSubview to keyWindow, if you add the view in the last. Otherwise, you can bringSubViewToFront.

let view = UIView()
UIApplication.shared.keyWindow?.addSubview(view)
UIApplication.shared.keyWindow?.bringSubviewToFront(view)

You can also set the zPosition. But the drawback is that you can not change the gesture responding order.

view.layer.zPosition = 1
Axil answered 24/12, 2019 at 8:43 Comment(0)
I
1

In c#, View.BringSubviewToFront(childView); YourView.Layer.ZPosition = 1; both should work.

Incapacious answered 22/5, 2019 at 15:51 Comment(0)
P
0

In Swift 4.2

UIApplication.shared.keyWindow!.bringSubviewToFront(yourView)

Source: https://developer.apple.com/documentation/uikit/uiview/1622541-bringsubviewtofront#declarations

Personalize answered 25/10, 2018 at 9:45 Comment(1)
No they changed in Swift 4.2, Please have a look at developer.apple.com/documentation/uikit/uiview/… @LuigiTairaPersonalize

© 2022 - 2024 — McMap. All rights reserved.