7
votes

I've created a custom tab bar that is displaying tab bar items correctly. When I select a tab / icon the tab bar item's view controller is displayed but the icon does not change to the 'Selected image' icon i.e. the icons don't change when their view controller is being shown.

What am I doing wrong? How can I get the icons to update to the images that I've set on IB as the selected images?

Here is some of my code:

class CustomTabBarController: UITabBarController, CustomTabBarDataSource, CustomTabBarDelegate {
 override func viewDidLoad() {
  super.viewDidLoad()
  self.tabBar.isHidden = true
  let customTabBar = CustomTabBar(frame: self.tabBar.frame)
  customTabBar.datasource = self
  customTabBar.delegate = self
  customTabBar.setup()
  self.view.addSubview(customTabBar)
 }
 // MARK: - CustomTabBarDataSource
 func tabBarItemsInCustomTabBar(_ tabBarView: CustomTabBar) -> [UITabBarItem] {
  return tabBar.items!
 }
 // MARK: - CustomTabBarDelegate
 func didSelectViewController(_ tabBarView: CustomTabBar, atIndex index: Int) {
  self.selectedIndex = index
 }   
}


class CustomTabBar: UIView {
 var tabBarItems: [UITabBarItem]!
 var customTabBarItems: [CustomTabBarItem]!
 var tabBarButtons: [UIButton]!

func setup() {
 tabBarItems = datasource.tabBarItemsInCustomTabBar(self)
 customTabBarItems = []
 tabBarButtons = []
 let containers = createTabBarItemContainers()
 createTabBarItems(containers)
}

func createTabBarItems(_ containers: [CGRect]) {

var index = 0
 for item in tabBarItems {
  let container = containers[index]
  let customTabBarItem = CustomTabBarItem(frame: container)
  customTabBarItem.setup(item)
  self.addSubview(customTabBarItem)
  customTabBarItems.append(customTabBarItem)
  let button = UIButton(frame: CGRect(x: 0, y: 0, width: container.width, height: container.height))
  button.addTarget(self, action: #selector(CustomTabBar.barItemTapped(_:)), for: UIControlEvents.touchUpInside)
  customTabBarItem.addSubview(button)
  tabBarButtons.append(button)
  index += 1
 }
}

func barItemTapped(_ sender : UIButton) {
 let index = tabBarButtons.index(of: sender)!
 delegate.didSelectViewController(self, atIndex: index)
}
3
Do the images exist in the Assets.xcassets?leanne
And, is there a reason you've set your CustomTabBar class to a subclass of UIView rather than UITabBar?leanne

3 Answers

1
votes

Change

class CustomTabBar: UIView {

to:

class CustomTabBar: UITabBar {

Then your custom tab bar will act like a tab bar!

1
votes

Well I had a same kind of functionality and implemented with UITabBarController like this.

enum TabType:Int{
case viewController1 = 0
case viewController2 = 1
case viewController3 = 2
}

class CustomTabbarVC: UITabBarController {

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

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    convenience init(userType : UserType){
        self.init()
        addViewControllers()
        setupOnInit()

        let tabBar = self.tabBar
        tabBar.selectionIndicatorImage = UIImage().createSelectionIndicator(UIColor(red: 22/255, green: 52/255, blue: 89/255, alpha: 1.0), size: CGSize(width: tabBar.frame.width/CGFloat(tabBar.items!.count), height: tabBar.frame.height), lineWidth: 3.0)
    }


    func setupOnInit(){

        delegate = self
        tabBar.barStyle = UIBarStyle.black
        tabBar.isTranslucent = false
    }

    func addViewControllers(){

        // We will add 3 controllers

        let viewController1 = viewController1(nibName: “viewController1”, bundle: nil)
        let viewController2 = viewController2(nibName: “viewController2”, bundle: nil)
        let viewController3 = viewController3(nibName: “viewController3”, bundle: nil)

        let viewController1Navigation =  UINavigationController(rootViewController: viewController1)
        viewController1Navigation.tabBarItem = getTabbarItem(.viewController1)
        viewController1Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)

        let viewController2Navigation =  UINavigationController(rootViewController: viewController2)
        viewController2Navigation.tabBarItem = getTabbarItem(.viewController2)
        viewController2Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)

        let viewController3Navigation =  UINavigationController(rootViewController: viewController3)
        viewController3Navigation.tabBarItem = getTabbarItem(.viewController3)
        viewController3Navigation.tabBarItem.imageInsets = UIEdgeInsetsMake(6, 0, -6, 0)

        viewControllers = [viewController1Navigation,viewController2Navigation,viewController3Navigation]

    }


    func getTabbarItem(_ tabType:TabType)->UITabBarItem{

        // Fetch tab bar item and set image according to it.

        var image = String()
        var selectedImage = String()

        if tabType == .viewController1{
            image = “img_viewController1_tab_nonSelected”
            selectedImage = “img_viewController1_tab_Selected”
        }else if tabType == .viewController2{
            image = “img_viewController2_tab_nonSelected”
            selectedImage = “img_viewController2_tab_Selected”
        }else if tabType == .viewController3{
            image = “img_viewController3_tab_nonSelected”
            selectedImage = “img_viewController3_tab_Selected”
        }else{
            print("Unknown tab type")
        }

        if let imageName:String = image,let selectedImageName:String = selectedImage{
            return UITabBarItem(title: nil, image: UIImage(named: imageName)?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage(named: selectedImageName)?.withRenderingMode(.alwaysOriginal))
        }else{
            return UITabBarItem()
        }
    }

}

extension UIImage {
    func createSelectionIndicator(_ color: UIColor, size: CGSize, lineWidth: CGFloat) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        color.setFill()
        UIRectFill(CGRect(x: 0, y: size.height - lineWidth, width: size.width, height: lineWidth))
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image!
    }
}

How to implement in App delegate

class AppDelegate: UIResponder, UIApplicationDelegate{

    var window: UIWindow?
    var customTabbarVC: CustomTabbarVC?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

         window = UIWindow(frame: UIScreen.main.bounds)
         customTabbarVC = customTabbarVC() // It will invoke init methods of customtabbarvc
         window?.rootViewController = customTabbarVC // Here your tab bar controller will setup 

        return true
     }

  // Other APP DELEGATE METHODS

}

Let me know if you have any questions..

1
votes

For Changing image in your custom tab bar button after you click the button you need to write the code to change image in below function

func barItemTapped(_ sender : UIButton) {
}

similarly

 func barItemTapped(_ sender : UIButton) 
{
    if sender.tag == 1
    {
    tabBarButtons.setImage(UIImage(named:"FirstImage.png"), forState: .Normal)
    }
    else
    {
    tabBarButtons.setImage(UIImage(named:"SecImage.png"), forState: .Normal)
    }
 }