Home > Mobile >  How to create a header layer that would stay the same over several ViewControllers?
How to create a header layer that would stay the same over several ViewControllers?

Time:10-13

I'd like to create a header that wouldn't move at all in my application that contains several ViewControllers. My header is simply a view containing a logo (UIImageView), a UIButton and a UILabel. I've heard that I can do that with a UINavigationController or by adding a subview to the UIWindow, but it doesn't work for me (maybe I'm doing it wrong). My main issue is to keep it fixed at the top of the screen (like a hud?) during segue animations, and I would also need to be able to modify the content of the UILabel during the application process.

I work on Xcode 13 with a storyboard for iOS 15 on iPad. Hope I've been clear enough.

EDIT It appears that inserting a view in the UIWindow would be the best solution for me, though I'm not sure how to do that properly. All the examples I find don't work and are deprecated/outdated.

CodePudding user response:

You can create a custom UITabBarController and then add it to SceneDelegate as -

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        
        let vc = CustomTab()
        self.window?.rootViewController = vc
        self.window?.makeKeyAndVisible()
        .......

In custom TabBar add all your navigation controllers as -

viewControllers = [nav1, nav2, nav3, nav4]

And in every view controller class you can hide, change or modify the tabbar prperties.

CodePudding user response:

So finally I succeeded using the method of Imran to which I added few things to match what I needed.

I have a singleton class for my header ViewController that contains the elements I needed inside of it.

let HEADER = STORYBOARD.instantiateViewController(withIdentifier: "HeaderLayer") as? HeaderViewController

class HeaderViewController: UIViewController {

    @IBOutlet weak var ThemeLabel: UILabel!
    @IBOutlet weak var DifficultyImage: UIImageView!
    @IBOutlet weak var ExitButton: UIButton!

    override func viewDidLoad() {
        super.viewDidLoad()
        // ...
    }

    // Methods
}

And here's how I put my header in the UIWindow to make it appear at the top of the screen, where it will stay fixed even during segue animations. I change the frame because if it's full screen it would disable the interactions for the views underneath.

let STORYBOARD = UIStoryboard(name: "Main", bundle: nil)

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    
        HEADER!.view.frame = CGRect(x: 0, y: 0, width: 1366, height: 142)
        window?.addSubview(HEADER!.view)
        window?.makeKeyAndVisible()
    
        // ...
    }
    // ...
}

Then it's necessary to bring the header to front everytime one of my ViewControllers appears.

class ViewController: UIViewController {

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
    
        let window = UIApplication.shared.keyWindow
        window?.bringSubviewToFront(HEADER!.view)
    
        // ...
    }
}

I'm not using any UINavigationController or UITabBarController, but it is possible with this method.

The only problem I encountered is that UIApplication.shared.keywindow is deprecated. But it doesn't seem to cause any issue and I didn't find a solution yet.

  • Related