8

Is it possible on iOS that a view always floats above all other views. I ask this because what I would like to achieve is a view that floats above a ViewController, and then a Modal View Controller slides in, whilst that particular view is still floating over that Modal View Controller (hope you get what I am trying to say).

thvanarkel
  • 1,601
  • 1
  • 12
  • 19

3 Answers3

9

There is. You can add your view to the main window and bring it to front when you have to.

In following code is presumed that _viewConroller and _anotherView are strong properties of appDelegate - configuration could of course be different.

This code would add small blue square on top left corner of the screen.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    _viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
    _anotherView = [[UIView alloc] initWithFrame: CGRectMake (0.0,0.0,20.0,20.0)];
    [anotherView setBackgroundColor: [UIColor blueColor]];    

    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];

    [self.window addSubView: _anotherView];
    [self.window bringSubViewToFront: _anotherView]; //not really needed here but it doesn't do any harm

    return YES;
}
Rok Jarc
  • 18,765
  • 9
  • 69
  • 124
  • I beleive it should, but i didn't try it out. It's possible you'll have to make a method to bring _anotherViewToFront and call it after viewControllers change places. – Rok Jarc Feb 26 '12 at 14:38
3

You can do the following if you are using storyboard and autolayout (inspired by the first Answer)

UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
UIViewController *_vc = [sb instantiateViewControllerWithIdentifier:@"FloatingController"];

_anotherView = _vc.view;
[_anotherView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.window addSubview: _anotherView];

[[VLBConstraintsGenerator sharedInstance] setWidth:200 forView:_anotherView inSuperView:_window];
[[VLBConstraintsGenerator sharedInstance] setHeight:200 forView:_anotherView inSuperView:_window];
[[VLBConstraintsGenerator sharedInstance] setLeading:0 forView:_anotherView inSuperView:_window];


[_anotherView setBackgroundColor:[UIColor grayColor]];

[[_anotherView layer] setBorderWidth:1];
[[_anotherView layer] setBorderColor:[UIColor yellowColor].CGColor];

[self.window makeKeyAndVisible];
[self.window bringSubviewToFront:_anotherView]; //not really needed here but it doesn't do any harm

all you need to do is to drag a view controller into you main storyboard with FloatingController as a storyboard ID

Additional Methods

-(void)setWidth:(CGFloat )theWidth forView:(UIView *)theView inSuperView:(UIView *)theSuperView

{
 assert([theSuperView isEqual:theView.superview]);
    NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:theView
                                                          attribute:NSLayoutAttributeWidth
                                                          relatedBy:NSLayoutRelationEqual
                                                             toItem:nil
                                                          attribute:NSLayoutAttributeNotAnAttribute
                                                         multiplier:1
                                                           constant:theWidth];


//    [cn setPriority:999];//make it variable according to the orientation
[theSuperView addConstraint:cn];
}


-(void)setHeight:(CGFloat )theHeight forView:(UIView *)theView inSuperView:(UIView *)theSuperView
{
assert([theSuperView isEqual:theView.superview]);

NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:theView
                                                      attribute:NSLayoutAttributeHeight
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:nil
                                                      attribute:NSLayoutAttributeNotAnAttribute
                                                     multiplier:1
                                                       constant:theHeight];

[theSuperView addConstraint:cn];
}

-(void)setLeading:(CGFloat )theLeading forView:(UIView *)theView inSuperView:(UIView *)theSuperView
{
assert([theSuperView isEqual:theView.superview]);

NSLayoutConstraint *cn = [NSLayoutConstraint constraintWithItem:theView
                                                      attribute:NSLayoutAttributeLeading
                                                      relatedBy:NSLayoutRelationEqual
                                                         toItem:theSuperView
                                                      attribute:NSLayoutAttributeLeading
                                                     multiplier:1
                                                       constant:theLeading];

[theSuperView addConstraint:cn];
}
Bobj-C
  • 5,276
  • 9
  • 47
  • 83
1

My solution to this problem is something like this. I will create UIView and inside will be UILabel.

first set up inside of some class:

 private var bannerLabel: UILabel = UILabel()
    private let view = UIView()

    // label background color 
    let greenColor = UIColorFromRGB(63,g: 161,b: 81)
    let warningColor = UIColorFromRGB(252,g: 140,b: 38)
    let errorColor = UIColorFromRGB(252,g: 66,b: 54)

After that, you add something like this.

func showBannerWithOption(title: String, color: UIColor) {
        view.frame = CGRect(x: 50, y: 150, width: 200, height: 45)
        let window = UIApplication.shared.keyWindow
        guard let mainWindow = window else { return }
        mainWindow.addSubview(view)

        view.centerXAnchor.constraint(equalTo: mainWindow.centerXAnchor).isActive = true
        view.centerYAnchor.constraint(equalTo: mainWindow.centerYAnchor).isActive = true

        bannerLabel.frame = CGRect(x: 50, y: 150, width: 200, height: 21)
        bannerLabel.backgroundColor = color
        bannerLabel.textColor = UIColor.black
        bannerLabel.textAlignment = .center
        bannerLabel.text = title
        view.addSubview(bannerLabel)
        bannerLabel.translatesAutoresizingMaskIntoConstraints = false

        bannerLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
        bannerLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
        bannerLabel.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
        bannerLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
    }

Just to explain, first I add a view and set up some CGRect after that I have set up a window (Main one) And inside of that, I add a view that is created.

After that, I have set up a label and set constraints to be equal with a view.

function showBannerWithOption with title and color is like this if you need it on more then one place.

if you want to call this function just do this:

    override func viewDidLoad() {
        super.viewDidLoad()
    showBannerWithOption(title: "test", color: greenColor) 
}

That is all :) This is swift 5.0

Now you can customize as you want.

tBug
  • 789
  • 9
  • 13