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.