myles
myles

Reputation: 1671

Insert subview behind TabBar from child view of TabBarController

I have TabBar with 2 tabs. At some point, from either of the 2 tabs, I want to add a view that is visible on both tab views but behind the TabBar.

So I thought, insert a subview into the TabBarController but below the TabBar.

This works fine in principle and I have the view behind the TabBar but now covering my 2 tabs as I wanted. However, it doesn't actually load. Just its background loads and only viewDidLoad() is called, not viewWillAppear() or any others.

I have also tried calling addChildViewController(myVC) on the TabBarController which has no effect, and also manually calling viewWillAppear() on the view controller I add which also has no effect (and I'm also dubious about whether manually calling viewWillAppear() is permitted or not?).

Is what I'm trying to do possible? What am I missing? Or should I be attempting this some other way?

Upvotes: 6

Views: 5881

Answers (5)

Egzon P.
Egzon P.

Reputation: 4778

Avoid using optionals for tabBarController or removing current tabBar. Simple add your view below tabBar view. Swift 5, XCode 11.

class TabBarController: UITabBarController {
    @IBOutlet var instructionsView: UIView!

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        self.view.insertSubview(instructionsView, belowSubview: self.tabBar)
    }
}

Upvotes: 1

Joshua Parmenter
Joshua Parmenter

Reputation: 23

you can also do this inside the init() method for your UITabViewController:

 view.insertSubview(alwaysVisibleView, belowSubview: self.tabBar)

no need to dispatch to another method if you are using a subclass of UITabViewController.

Upvotes: 0

Justin Stanley
Justin Stanley

Reputation: 362

This would be a good way:

Add the function below and call it in viewDidLoad of your initial VC. It unwraps your tab bar controller instance (which is optional), and then inserts the view you always want visible just below the tab bar.

private func setupAlwaysVisibleView() {
    guard let tabBarController = self.tabBarController else { return }

    tabBarController.view.insertSubview(alwaysVisibleView, belowSubview: tabBarController.tabBar)
}

Upvotes: 1

Kesong Xie
Kesong Xie

Reputation: 1396

There is no need to remove and recreate the tabBar. What you need to do is after you insert your custom view, you can then bring the tabBar to the front again.

//bring the tabBar to the front after inserting new view
self.view.bringSubview(toFront: self.tabBar)

Upvotes: 1

myles
myles

Reputation: 1671

For some reason, when inserting a subview into a UITabBarController behind it's UITabBar, although the view is visible to the user, the system itself seems to think it is not and so although viewDidLoad() is called, viewDidAppear() and subsequent methods are not.

However, adding a subview above the UITabBar seems to work fine. So I solved this by adding my own new UITabBar as a subview to the UITabBarController (set up basically exactly as the default one would be) and then removing the UITabBarController's default UITabBar.

Then when later inserting my view into the UITabBarController, I insert it as I was doing originally but instead below/behind my custom UITabBar and it seems to load fine.

Upvotes: 3

Related Questions