I am creating a sample app which contains TabBarViewController and also i implement slide menu using SWRevealViewController and the problem is that the slide menu it not showing out.
Here i set rootViewController in appdelegate
window = UIWindow(frame: UIScreen.main.bounds)
window?.makeKeyAndVisible()
window?.rootViewController = TabBarController()
Here is my TabBarController which i implement 2 tabBar items which first tabBar item should have slide menu
let homeController = HomeController()
let homeNavigation = UINavigationController(rootViewController: homeController)
homeNavigation.tabBarItem.title = "Home"
let menuController = MenuViewController()
let swReveal = SWRevealViewController(rearViewController: homeNavigation, frontViewController: menuController)
swReveal?.toggleAnimationType = SWRevealToggleAnimationType.easeOut
swReveal?.toggleAnimationDuration = 0.30
let favController = FavoriteController()
let favNavigation = UINavigationController(rootViewController: favController)
favNavigation.tabBarItem.title = "Favorite"
viewControllers = [homeNavigation, favNavigation]
For MenuController i setup some navigation button for showing menu
let menuButton = UIBarButtonItem(title: "Menu", style: .plain, target: self.revealViewController(), action: #selector(slideMenu))
self.navigationItem.leftBarButtonItem = menuButton
#objc func slideMenu() {
if revealViewController() != nil {
revealViewController().revealToggle(animated: true)
revealViewController().rearViewRevealWidth = (view.bounds.width * 80 ) / 100
}
else {
print("no reveal view")
}
}
You need to configure SWRevealViewController in your didFinishLaunchingWithOptions method as shown below:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let frontNavigationController:UINavigationController
let rearNavigationController:UINavigationController
let revealController = SWRevealViewController()
var mainRevealController = SWRevealViewController()
frontNavigationController = UINavigationController(rootViewController: TabBarController())
rearNavigationController = UINavigationController(rootViewController: MenuViewController())
frontNavigationController.navigationBar.isHidden = true
rearNavigationController.navigationBar.isHidden = true
revealController.frontViewController = frontNavigationController
revealController.rearViewController = rearNavigationController
revealController.delegate = self
mainRevealController = revealController
window = UIWindow(frame: UIScreen.main.bounds)
self.window?.rootViewController = mainRevealController
self.window?.makeKeyAndVisible()
return true
}
And in your HomeController replace
let menuButton = UIBarButtonItem(title: "Menu", style: .plain, target: self.revealViewController(), action: #selector(slideMenu))
with
let menuButton = UIBarButtonItem(title: "Menu", style: .plain, target: self, action: #selector(slideMenu))
And remove
let menuController = MenuViewController()
let swReveal = SWRevealViewController(rearViewController: homeNavigation, frontViewController: menuController)
swReveal?.toggleAnimationType = SWRevealToggleAnimationType.easeOut
swReveal?.toggleAnimationDuration = 0.30
From your TabBarController and your final code will be:
func customTabbar (){
let homeController = HomeController()
let homeNavigation = UINavigationController(rootViewController: homeController)
homeNavigation.tabBarItem.title = "Home"
let favController = FavoriteController()
let favNavigation = UINavigationController(rootViewController: favController)
favNavigation.tabBarItem.title = "Favorite"
let servicePhoneCollectionFLowLayoutInstance = UICollectionViewFlowLayout()
let serviceTabbarFlowLayoutInit = ExploreController(collectionViewLayout: servicePhoneCollectionFLowLayoutInstance)
let exploreController = serviceTabbarFlowLayoutInit
let exploreNavigation = UINavigationController(rootViewController: exploreController)
exploreNavigation.tabBarItem.title = "Explore"
let moreController = DetailViewController()
let moreViewController = UINavigationController(rootViewController: moreController)
moreViewController.tabBarItem.title = "Tools"
viewControllers = [homeNavigation, favNavigation, exploreNavigation, moreViewController]
}
And for more info check your updated project HERE.
Here is Working Code of SWRevealViewController with UINavigationController and UITabBarController by Storyboard (Swift 4)
https://stackoverflow.com/a/51725803/10150796
Related
I have a tab bar controller that shows 5 tabs. It shows perfectly in iOS 12 or earlier as shown here
.
But if I run the same in iOS 13, the design is totally messed up
.
It totally loses the scroll view insets, and it is also not adjusting the bottom insets of my menus table view. some of the menus are hidden in the bottom. they are not scrolling up. and this is the code that I'm using in UITabBarController
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
guard let user = user else {
appDelegate.instituteSelectionView()
return
}
var dashBoard: UINavigationController
var menus: UINavigationController? = nil
// Creating all the view controllers for tabs.
if user.role.caseInsensitiveCompare("student") == .orderedSame {
let dashBoardVC = mainStoryBoard.instantiateViewController(withIdentifier: "DashboardVC") as! DashboardVC
dashBoardVC.menus = ContentProvider.getMenus()
dashBoardVC.school = user.school
dashBoard = UINavigationController(rootViewController: dashBoardVC)
dashBoard.navigationBar.prefersLargeTitles = true
} else {
let dashBoardVC = mainStoryBoard.instantiateViewController(withIdentifier: "DashboardWidgetsTableViewController") as! DashboardWidgetsTableViewController
dashBoardVC.user = user
dashBoardVC.title = "Dashboard"
dashBoard = UINavigationController(rootViewController: dashBoardVC)
let menusVC = mainStoryBoard.instantiateViewController(withIdentifier: "MenusTableViewController") as! MenusTableViewController
menusVC.setMenus(ContentProvider.getMenusForStaff())
menus = UINavigationController(rootViewController: menusVC)
}
dashBoard.tabBarItem = UITabBarItem(title: "Dashboard", image: #imageLiteral(resourceName: "dashboard"), tag: 0)
if menus != nil {
menus?.navigationBar.prefersLargeTitles = true
menus?.tabBarItem = UITabBarItem(title: "Menus", image: #imageLiteral(resourceName: "menu-1"), tag: 1)
}
let notificationVC = mainStoryBoard.instantiateViewController(withIdentifier: "NotificationsTabTableViewController") as! NotificationsTabTableViewController
notificationVC.user = user
let notification = UINavigationController(rootViewController: notificationVC)
notification.tabBarItem = UITabBarItem(title: "Notifications", image: #imageLiteral(resourceName: "bell"), tag: 3)
notification.tabBarItem.badgeValue = user.badge > 0 ? String(user.badge) : nil
notification.navigationBar.prefersLargeTitles = true
let settingsVC = mainStoryBoard.instantiateViewController(withIdentifier: "SettingsTabTableViewController") as! SettingsTabTableViewController
settingsVC.user = user
let settings = UINavigationController(rootViewController: settingsVC)
settings.tabBarItem = UITabBarItem(title: "Settings", image: #imageLiteral(resourceName: "settings"), tag: 4)
settings.navigationBar.prefersLargeTitles = true
let accountsVC = mainStoryBoard.instantiateViewController(withIdentifier: "AccountsTableViewController") as! AccountsTableViewController
let accounts = UINavigationController(rootViewController: accountsVC)
accounts.tabBarItem = UITabBarItem(title: "Accounts", image: #imageLiteral(resourceName: "user_group_man_man"), tag: 5)
accounts.navigationBar.prefersLargeTitles = true
mViewControllers = [dashBoard, notification, settings, accounts]
if menus != nil {
mViewControllers.insert(menus!, at: 1)
}
// Adding logo and profile button to navigation bar of each view controller.
for vc in mViewControllers {
if let nVC = vc as? UINavigationController, let vc = nVC.topViewController {
let logo = UIImageView(image: #imageLiteral(resourceName: "educare logo"))
logo.contentMode = .scaleAspectFill
logo.clipsToBounds = true
logo.widthAnchor.constraint(equalToConstant: 24).isActive = true
logo.heightAnchor.constraint(equalToConstant: 24).isActive = true
let profileButton = UIButton(type: .custom)
profileButton.widthAnchor.constraint(equalToConstant: 24).isActive = true
profileButton.heightAnchor.constraint(equalToConstant: 24).isActive = true
profileButton.imageView?.layer.cornerRadius = 12
if #available(iOS 13.0, *) {
let image = UIImage(systemName: "person.crop.circle")
profileButton.sd_setImage(with: URL(string: user.image), for: .normal, placeholderImage: image)
} else {
profileButton.sd_setImage(with: URL(string: user.image), for: .normal, placeholderImage: #imageLiteral(resourceName: "user_circle"))
}
profileButton.addTarget(self, action: #selector(openProfile), for: .touchUpInside)
let logoButtonItem = UIBarButtonItem(customView: logo)
let profileButtonItem = UIBarButtonItem(customView: profileButton)
vc.navigationItem.leftBarButtonItem = logoButtonItem
vc.navigationItem.rightBarButtonItems = [profileButtonItem]
}
}
setViewControllers(mViewControllers, animated: true)
}
Update: Actually the first view controller in the tab bar controller renders correctly but the rest of the view controllers have that ugly navigation bar.
I Solved the problem. turns out it was the transition animation (from the initial view controller to the main tab bar controller) that was causing the problem. So i changed the code from this
if animated {
UIView.transition(from: (window?.rootViewController?.view)!, to: viewController.view, duration: duration, options: animationOptions) { (completed) in
if completed {
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
}
}
} else {
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
}
to this
guard let window = UIApplication.shared.keyWindow else { return }
window.rootViewController = viewController
window.makeKeyAndVisible()
if animated {
UIView.transition(with: window, duration: duration, options: animationOptions, animations: {})
}
I use tabBarController to create a music program and I have questions like how to do it as shown in gif
Questions:
How to do so that when you click on tabBarItem, "presentViewController" worked
How to make it so that the photo does not change color and make it round, only in the third tabBarItem
Preferably without libraries
it should be
My TabBarController
override func viewDidLoad() {
super.viewDidLoad()
self.delegate = self
// меняет цвет фона tabBar
self.tabBar.barTintColor = .white
// меняет цвет UITabBarItem and Title
UITabBar.appearance().tintColor = UIColor(hex: 0x0077fe, alpha: 1)
//меняет цвет background UITabBar
UITabBar.appearance().barTintColor = UIColor.white
// делает фон серым
for item in self.tabBar.items! {
if let image = item.image {
item.image = image.withRenderingMode(.alwaysOriginal)
}
}
//показывает и переходит в контроллеры
let storyBoard = UIStoryboard(name: "Main", bundle:nil)
let controller1 = storyBoard.instantiateViewController(withIdentifier: "main") as! VCMain
let controller2 = storyBoard.instantiateViewController(withIdentifier: "search")
let controller3 = storyBoard.instantiateViewController(withIdentifier: "player")
let controller4 = storyBoard.instantiateViewController(withIdentifier: "bookmark")
let controller5 = storyBoard.instantiateViewController(withIdentifier: "menu")
self.setViewControllers([controller1,controller2,controller3,controller4,controller5], animated: true)
// создает навигационный контроллер для контроллеров
let vc1 = UINavigationController(rootViewController: controller1)
let vc2 = UINavigationController(rootViewController: controller2)
let vc3 = UINavigationController(rootViewController: controller3)
let vc4 = UINavigationController(rootViewController: controller4)
let vc5 = UINavigationController(rootViewController: controller5)
viewControllers = [vc1, vc2, vc3, vc4, vc5]
}
override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
print(item.tag)
if item.tag == 0{
if GlobalModals.count != 0 {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "player") as? VCPlayer
self.present(vc!, animated: true, completion: nil)
}
}
}
Player
override func viewDidLoad() {
super.viewDidLoad()
let im = Extension.resizeImage(image:GlobalModals[thisSong].ImageView! , targetSize: CGSize.init(width:20, height: 20))
self.tabBarController?.tabBar.items![2].image = im
}
}
The TabBarController doesn't have those option, you need to implement it by subclassing.
You can use this library Animated Tab Bar to achieve the same result with animation.
I created a view and a button on it in tabBarController and created a func that sets the parameters and call it after I set all the view controllers also created a notificationCenter that could change the button image from another controller
class TabBarController: UITabBarController,UITabBarControllerDelegate {
open var playerBtn = UIButton()
//func for NotificationCenter
#objc func imageChange() {
if GlobalModals.count != 0 {
playerBtn.setImage(GlobalModals[thisSong].ImageView, for: .normal)
}
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(imageChange), name: NSNotification.Name(rawValue: "imageChange"), object: nil)
self.delegate = self
//shows and goes to controllers
let storyBoard = UIStoryboard(name: "Main", bundle:nil)
let controller1 = storyBoard.instantiateViewController(withIdentifier: "main") as! VCMain
let controller2 = storyBoard.instantiateViewController(withIdentifier: "search")
let controller3 = storyBoard.instantiateViewController(withIdentifier: "player")
let controller4 = storyBoard.instantiateViewController(withIdentifier: "bookmark")
let controller5 = storyBoard.instantiateViewController(withIdentifier: "menu")
self.setViewControllers([controller1,controller2,controller4,controller5], animated: true)
// creates navigation controller
let vc1 = UINavigationController(rootViewController: controller1)
let vc2 = UINavigationController(rootViewController: controller2)
let vc3 = UINavigationController(rootViewController: controller3)
let vc4 = UINavigationController(rootViewController: controller4)
let vc5 = UINavigationController(rootViewController: controller5)
viewControllers = [vc1, vc2, vc3, vc4, vc5]
self.setupMiddleButton()
}
// TabBarButton – Setup Middle Button and View
func setupMiddleButton() {
playerBtn.frame = CGRect(x: 0, y: 0, width: 45, height: 45)
var playerBtnFrame = playerBtn.frame
playerBtnFrame.origin.y = self.view.bounds.height - playerBtnFrame.height - 2
playerBtnFrame.origin.x = self.view.bounds.width / 2 - playerBtnFrame.size.width / 2
playerBtn.frame = playerBtnFrame
playerBtn.layer.cornerRadius = playerBtnFrame.height/2
playerBtn.layer.masksToBounds = true
playerBtn.contentMode = .scaleAspectFill
let view = UIView()
let width = self.view.frame.width/5
let xWidth = width*2
view.frame = CGRect(x: xWidth , y: playerBtnFrame.origin.y - 2, width: self.view.frame.width/5, height: tabBar.frame.height)
view.backgroundColor = .clear
self.view.addSubview(view)
self.view.addSubview(playerBtn)
playerBtn.setImage(UIImage(named: "home"), for: UIControlState.normal)
playerBtn.addTarget(self, action: #selector(playerButtonAction), for: UIControlEvents.touchUpInside)
self.view.layoutIfNeeded()
}
// Button Touch Action
#objc func playerButtonAction(sender: UIButton) {
if GlobalModals.count != 0 {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "player") as? VCPlayer
self.present(vc!, animated: true, completion: nil)
}
}
}
so I change the image of the button
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "imageChange"), object: nil)
let tabBarController = UITabBarController()
let VC1 = ConstDetailViewController()
VC1.tabBarItem.image = UIImage(named: "Home.Re.png")
let VC1Navigation = UINavigationController(rootViewController: VC1)
let VC2 = LeaderboardViewController()
VC2.tabBarItem.image = UIImage(named: "search3.png")
let VC2Navigation = UINavigationController(rootViewController: VC2)
let VC3 = MapViewViewController()
VC3.tabBarItem.image = UIImage(named: "graphRe.png")
let VC3Navigation = UINavigationController(rootViewController: VC3)
let VC4 = UserProfileViewController()
VC4.tabBarItem.image = UIImage(named: "UserRe.png")
let VC4Navigation = UINavigationController(rootViewController: VC4)
let loginVC = ConstituencyViewController()
let VC5Navigation = UINavigationController(rootViewController: loginVC)
let controllers = [VC1Navigation, VC2Navigation,VC3Navigation,VC4Navigation]
tabBarController.viewControllers = controllers
self.window!.backgroundColor = UIColor.white
self.window?.rootViewController = VC5Navigation
self.window!.makeKeyAndVisible()
I have configured tab bar in my appdelegate. But now I am missing my tab bar. It shows a blank space in the place of tab bar. Please help me resolve the issue.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let tabBarController = UITabBarController()
let VC1 = UIViewController()
VC1.tabBarItem.image = UIImage(named: "Home.Re.png")
let VC1Navigation = UINavigationController(rootViewController: VC1)
let VC2 = UIViewController()
VC2.tabBarItem.image = UIImage(named: "search3.png")
let VC2Navigation = UINavigationController(rootViewController: VC2)
let VC3 = UIViewController()
VC3.tabBarItem.image = UIImage(named: "graphRe.png")
let VC3Navigation = UINavigationController(rootViewController: VC3)
let VC4 = UIViewController()
VC4.tabBarItem.image = UIImage(named: "UserRe.png")
let VC4Navigation = UINavigationController(rootViewController: VC4)
let loginVC = UIViewController()
let VC5Navigation = UINavigationController(rootViewController: loginVC)
let controllers = [VC1Navigation, VC2Navigation,VC3Navigation,VC4Navigation]
tabBarController.viewControllers = controllers
self.window!.backgroundColor = UIColor.white
self.window?.rootViewController = tabBarController //TabBarController
self.window!.makeKeyAndVisible()
return true
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
self.window?.backgroundColor = UIColor.white
self.window?.makeKeyAndVisible()
let tabBarController = UITabBarController()
let myVC1 = ViewController(nibName: "ViewController", bundle: nil)
let myVC2 = ViewController1(nibName: "ViewController1", bundle: nil)
let controllers = [myVC1,myVC2]
tabBarController.viewControllers = controllers
window?.rootViewController = tabBarController
let firstImage = UIImage(named: "Search")
let secondImage = UIImage(named: "Search1")
myVC1.tabBarItem = UITabBarItem(
title: "Pie",
image: firstImage,
tag: 1)
myVC2.tabBarItem = UITabBarItem(
title: "Pizza",
image: secondImage,
tag:2)
// Override point for customization after application launch.
return true
A black screen appears whenever I run the app.
I think you did not pervoid UIWindow size
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UITabBarController()
or you some problem with setting root view controller.
You need to add window = UIWindow at the beginning of app Delegate didFinishLaunchingWithOptions: or else there isn't a frame size set. Thats why your getting the black screen.
window = UIWindow(frame: UIScreen.main.bounds)
self.window?.backgroundColor = UIColor.white
let tabBarController = UITabBarController()
let myVC1 = UIViewController()
let myVC2 = UIViewController()
let controllers = [myVC1,myVC2]
I have an app with a UITabBarController as my initial view controller.
Currently I'm doing everything in Storyboard but I want to programmatically add a tab to the tab bar based on a user being logged in or not.
I made a TestViewController to test this out. Right now I have two tabs (pictured below). I want to have a third tab positioned on the right programmatically. I put this code in my AppDelegate's didFinishLaunching method. Based on print statements the view controller is being added to the tab bar but it is not appearing in the tab bar then the app loads.
Any suggestions?
func addTabTEST() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let tabController = storyboard.instantiateViewControllerWithIdentifier("RootTabController") as! UITabBarController
let TestVC = storyboard.instantiateViewControllerWithIdentifier("TestViewController") as! TestViewController
let icon = UITabBarItem(title: "test", image: nil, selectedImage: nil)
TestVC.tabBarItem = icon
print("TAB CONTROLLERS 1: \(tabController.viewControllers)")
tabController.addChildViewController(TestVC)
tabController.viewControllers![2] = TestVC
print("TAB CONTROLLERS 2: \(tabController.viewControllers)")
}
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let nav1 = UINavigationController()
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let first: ViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ViewController") as! ViewController
nav1.viewControllers = [first]
nav1.setNavigationBarHidden(true, animated: true)
nav1.title = "first"
let nav2 = UINavigationController()
let second: SecondViewController = mainStoryboard.instantiateViewControllerWithIdentifier("SecondViewController") as! SecondViewController
nav2.viewControllers = [second]
nav2.setNavigationBarHidden(true, animated: true)
nav2.title = "second"
let nav3 = UINavigationController()
let third: ThirdViewController = mainStoryboard.instantiateViewControllerWithIdentifier("ThirdViewController") as! ThirdViewController
nav3.viewControllers = [third]
nav3.setNavigationBarHidden(true, animated: true)
nav3.title = "third"
let tabController = UITabBarController()
tabController.viewControllers = [nav1,nav2,nav3]
tabController.selectedIndex = 0
self.window!.rootViewController = tabController
self.window?.makeKeyAndVisible()
this is for swift 4
self.window = UIWindow(frame: UIScreen.main.bounds)
let nav1 = UINavigationController()
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let first = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController") as! HomeViewController
nav1.viewControllers = [first]
nav1.setNavigationBarHidden(true, animated: true)
nav1.title = "first"
let nav2 = UINavigationController()
let second: HomeViewController = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController2") as! HomeViewController2
nav2.viewControllers = [second]
nav2.setNavigationBarHidden(true, animated: true)
nav2.title = "second"
let nav3 = UINavigationController()
let third = mainStoryboard.instantiateViewController(withIdentifier: "HomeViewController3") as! HomeViewController3
nav3.viewControllers = [third]
nav3.setNavigationBarHidden(true, animated: true)
nav3.title = "third"
let tabController = UITabBarController()
tabController.viewControllers = [nav1,nav2,nav3]
tabController.selectedIndex = 0
self.window!.rootViewController = tabController
self.window?.makeKeyAndVisible()
if you do not want to use UIStoryboard and if you have three view controllers named oneVC, twoVC, and threeVC you can use (works on Swift 5.3 with iOS 14.2)
let window = UIWindow(frame: UIScreen.main.bounds)
window.backgroundColor = .systemBackground
self.window = window
// Put image path if you want to have an image on your TabBar for this view controller
self.oneVC?.tabBarItem = UITabBarItem(title: "One", image: nil, selectedImage: nil)
self.twoVC?.tabBarItem = UITabBarItem(title: "Two", image: nil, selectedImage: nil)
self.threeVC?.tabBarItem = UITabBarItem(title: "Three", image: nil, selectedImage: nil)
let tabController = UITabBarController()
tabController.viewControllers = [oneVC, twoVC, threeVC]
tabController.selectedIndex = 0
self.window!.rootViewController = tabController
self.window?.makeKeyAndVisible()