What is the best approach for creating a custom tab bar controller?

I am working on an application, which is more likely a tabBarController application. But I cannot use tabBarController because I need my own tab handler at the bottom, I also need to adjust the space between the elements. Therefore, I create a custom tabBarController .

I would like to know a better approach. Currently my approach is this (using storyboard and iOS6 ): - I adopted the UIToolbar on the ViewController , which will act as the bottom panel of the tab (CustomTabBarViewController). I took ContainerViews for each tab. When the user selects an item on the toolbar , I show that containerView .

Please tell me if I am wrong or direct the best way. Thanks.

+6
source share
4 answers

You are very mistaken. Do not create your own view hierarchy if you can just use it by default.

What you want to do is create a subclass of UITabBarController and also create a .xib file that will contain your own tab bar - just an image and an arbitrary number of UIButtons (I assume 5).

enter image description here

Set tags for all of them, just 1-5 tags, you can do it with a custom subclass of UIView , but that will be superfluous in this scenario, so it will just be a selection of controls using tags.

Create a subclass of UITabBarController . You will need links to all of these buttons, as well as a property, to see which button was last pressed so that you can update the interface accordingly. Also assign different images or captions for different control states, I use the default and selected in this case.

MYBaseTabBarController.h

 @interface MYBaseTabBarController : UITabBarController @property (strong, nonatomic) UIButton *btn1; @property (strong, nonatomic) UIButton *btn2; @property (strong, nonatomic) UIButton *btn3; @property (strong, nonatomic) UIButton *btn4; @property (strong, nonatomic) UIButton *btn5; @property (weak, nonatomic) UIButton *lastSender; @property (strong, nonatomic) UIView *tabBarView; @end 

MYBaseTabBarController.m

First of all, create view controllers (which in this case are subclasses of UINavigationController ) and assign them to your subclass UITabBarController as a property of viewControllers .

 - (id)init { self = [super init]; if (self) { [self setup]; } return self; } - (void)setup { NSMutableArray *viewControllers = [NSMutableArray array]; MYViewController1 *viewController1 = [[MYStoryboardManager storyboard1] instantiateInitialViewController]; viewController1.title = @"1"; [viewControllers addObject:viewController1]; MYViewController2 *viewController2 = [[MYStoryboardManager storyboard2] instantiateInitialViewController]; viewController2.title = @"2"; [viewControllers addObject:viewController2]; UIViewController *blankController = [UIViewController new]; // Center button, performs an action instead of leading to a controller [viewControllers addObject:blankController]; MYViewController3 *viewController3 = [[MYStoryboardManager storyboard3] instantiateInitialViewController]; viewController3.title = @"3"; [viewControllers addObject:viewController3]; MYViewController3 *viewController4 = [[MYStoryboardManager storyboard4] instantiateInitialViewController]; viewController4.title = @"4"; [viewControllers addObject:viewController4]; self.viewControllers = viewControllers; } 

Then take the buttons you created earlier and assign them actions in the -viewDidLoad method:

 - (void)viewDidLoad { [super viewDidLoad]; _tabbarView = [[[NSBundle mainBundle] loadNibNamed:@"MyTabBar" owner:nil options:nil] lastObject]; // "MyTabBar" is the name of the .xib file _tabbarView.frame = CGRectMake(0.0, self.view.frame.size.height - _tabbarView.frame.size.height, _tabbarView.frame.size.width, _tabbarView.frame.size.height); // make it overlay your actual tab bar [self.view addSubview:_tabbarView]; _btn1 = (UIButton *)[_tabbarView viewWithTag:1]; [_btn1 addTarget:self action:@selector(processBtn:) forControlEvents:UIControlEventTouchUpInside]; _btn2 = (UIButton *)[_tabbarView viewWithTag:2]; [_btn2 addTarget:self action:@selector(processBtn:) forControlEvents:UIControlEventTouchUpInside]; _btn3 = (UIButton *)[_tabbarView viewWithTag:3]; [_btn3 addTarget:self action:@selector(processBtn:) forControlEvents:UIControlEventTouchUpInside]; _btn4 = (UIButton *)[_tabbarView viewWithTag:4]; [_btn4 addTarget:self action:@selector(processBtn:) forControlEvents:UIControlEventTouchUpInside]; _btn5 = (UIButton *)[_tabbarView viewWithTag:5]; [_btn5 addTarget:self action:@selector(processBtn:) forControlEvents:UIControlEventTouchUpInside]; _lastSender = _btn1; [self setSelectedViewController:self.viewControllers[0]]; // make first controller selected } 

Add a processing method:

 - (void)processBtn:(UIButton *)sender { _lastSender = sender; [self setSelectedViewController:[self.viewControllers objectAtIndex:sender.tag - 1]]; } 

Finally, override the -setSelectedViewController: method:

 - (void)setSelectedViewController:(UIViewController *)selectedViewController { if (_lastSender != _btn3) { // check if it not the action button for (UIButton *btn in [_tabbarView subviews]) { if ([btn isKindOfClass:[UIButton class]]) { if (btn == _lastSender) { btn.selected = YES; } else { btn.selected = NO; } } } } if ([self.viewControllers indexOfObject:selectedViewController] == 2) { MYActionController *viewController = [[MYStoryboardManager actionStoryboard] instantiateInitialViewController]; [self presentViewController:viewController animated:YES completion:nil]; } else { if (self.selectedViewController == selectedViewController) { [(UINavigationController *)self.selectedViewController popToRootViewControllerAnimated:animate]; // pop to root if tapped the same controller twice } [super setSelectedViewController:selectedViewController]; } } 

I assume that you are programming with ARC enabled and that you have a class that manages your storyboards, but in any case it's pretty simple.

+15
source

Below code works fine in my project.

I used the swift3 version as shown below:

i added a file MyTabBar.xib containing a UIView with 4 buttons. In the xib file, set the UIView class. class = "MyTabBar"
Give 4 Tag buttons 1,2,3,4 respectively ..

and below myTabBarController file

myTabBarController.swift as shown below:

 class myTabBarController: UITabBarController { var tabBarView: UIView! var btn1: UIButton! var btn2: UIButton! var btn3: UIButton! var btn4: UIButton! var lastSender: UIButton! var categoryViewController: CategoryViewController? var subCategoryViewController: SubCategoryViewController? var scoreViewController: ScoreViewController? var profileViewController: ProfileViewController? override func viewDidLoad() { super.viewDidLoad() self.setup() tabBarView = Bundle.main.loadNibNamed("MyTabBar", owner: nil, options: nil)?.last as! UIView tabBarView.frame = CGRect(x: 0.0, y: self.view.frame.size.height - tabBarView.frame.size.height, width: tabBarView.frame.size.width, height: tabBarView.frame.size.height) self.view.addSubview(tabBarView) btn1 = tabBarView.viewWithTag(1) as? UIButton btn1.addTarget(self, action: #selector(self.processBtn), for: .touchUpInside) btn2 = tabBarView.viewWithTag(2) as? UIButton btn2.addTarget(self, action: #selector(self.processBtn), for: .touchUpInside) btn3 = tabBarView.viewWithTag(3) as? UIButton btn3.addTarget(self, action: #selector(self.processBtn), for: .touchUpInside) btn4 = tabBarView.viewWithTag(4) as? UIButton btn4.addTarget(self, action: #selector(self.processBtn), for: .touchUpInside) let width1 = self.view.frame.width/4 btn1.frame = CGRect(x: 0, y: 0, width: width1, height: tabBarView.frame.size.height) btn2.frame = CGRect(x: btn1.frame.width, y: 0, width: width1, height: tabBarView.frame.size.height) btn3.frame = CGRect(x: btn2.frame.origin.x+btn2.frame.width, y: 0, width: width1, height: tabBarView.frame.size.height) btn4.frame = CGRect(x: btn3.frame.origin.x+btn3.frame.width, y: 0, width: width1, height: tabBarView.frame.size.height) lastSender = btn1 selectedViewController = viewControllers?[0] } func processBtn(_ sender: UIButton) { lastSender = sender selectedViewController = viewControllers?[sender.tag - 1] if sender.tag == 1 { btn1.backgroundColor = UIColor.red btn2.backgroundColor = UIColor.yellow btn3.backgroundColor = UIColor.yellow btn4.backgroundColor = UIColor.yellow }else if sender.tag == 2 { btn1.backgroundColor = UIColor.yellow btn2.backgroundColor = UIColor.red btn3.backgroundColor = UIColor.yellow btn4.backgroundColor = UIColor.yellow }else if sender.tag == 3 { btn1.backgroundColor = UIColor.yellow btn2.backgroundColor = UIColor.yellow btn3.backgroundColor = UIColor.red btn4.backgroundColor = UIColor.yellow }else if sender.tag == 4 { btn1.backgroundColor = UIColor.yellow btn2.backgroundColor = UIColor.yellow btn3.backgroundColor = UIColor.yellow btn4.backgroundColor = UIColor.red } } func setup() { var viewControllers = [AnyObject]() categoryViewController = self.storyboard!.instantiateViewController(withIdentifier: "CategoryViewController") as? CategoryViewController viewControllers.append(categoryViewController!) subCategoryViewController = self.storyboard!.instantiateViewController(withIdentifier: "SubCategoryViewController") as? SubCategoryViewController viewControllers.append(subCategoryViewController!) scoreViewController = self.storyboard!.instantiateViewController(withIdentifier: "ScoreViewController") as? ScoreViewController viewControllers.append(scoreViewController!) profileViewController = self.storyboard!.instantiateViewController(withIdentifier: "ProfileViewController") as? ProfileViewController viewControllers.append(profileViewController!) self.viewControllers = viewControllers as? [UIViewController] } func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool { for view in tabBarView.subviews as [UIView] { if let btn = view as? UIButton { if btn == lastSender { btn.isSelected = true } else { btn.isSelected = false } } } if self.selectedViewController == viewController { (self.selectedViewController as? UINavigationController)?.popToRootViewController(animated: true) // pop to root if tapped the same controller twice } return (viewController != tabBarController.selectedViewController) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } 

}

This way you can create your own tabs to suit your needs.

thanks

+2
source

Below is the step to make the following presentation: -

1: Take the UITabBarController and set it as rootViewController of your application window.

2: add Five Tab to this UITabbarController.

3: Add five separate UINavigationController to each tab individually.

4: Now add five different UIViewControllers to the UINavigationController respectively.

5: Create a custom tab:

5.1. One way to create a custom tab is to take the tabs UIView and add the UIButtons as Tab to the Tabbar.

6: add Custom TabBar to MainWindow. When selecting a different button on your custom tab, change the setSelectedIndex of your UITabbarController application.

0
source

For ios 9.0+ use UIStackView in horizontal direction and create xib and name it CustomTabBarView

CustomTabBarView.Xib insert uistackview in it

Set stack view attributes like this

Create another CustomTabBarItem view.

CustomTabBarItem.xib enter image description here

create a CustomTabBarItem.swift file to implement TabItem functionality

 class CustomTabItem: UIView { //MARK:- IBOutlets @IBOutlet weak var itemImage: UIImageView! @IBOutlet weak var itemTitle: SelectableLabel! @IBOutlet weak var topButton: UIButton! //MARK:- Variables var isSelected: Bool = false { didSet { self.itemImage.image = CommonFunctions.getTabItemImage(isSelected: isSelected, tag: topButton.tag) itemTitle.isSelected = isSelected if isSelected { self.backgroundColor = UIColor.appDarkBlueColor } else { self.backgroundColor = UIColor.appWhiteColor } } } //MARK:- IBActions @IBAction func onClickButton(_ sender: Any) { } 

}

In TabBarViewController Inject this code

 func createCustomTabBarView(tabItemCount: Int){ customTabBarView = Bundle.main.loadNibNamed("CustomTabBarView", owner: nil, options: nil)?.last as! UIView customTabBarView.frame = CGRect(x: 0, y: self.view.frame.height - self.tabBar.frame.height, width: self.tabBar.frame.width, height: self.tabBar.frame.size.height) self.view.addSubview(customTabBarView) var stackView = UIStackView() for subView in customTabBarView.subviews{ if subView is UIStackView { stackView = subView as! UIStackView } } for i in 0..<tabItemCount { let customTabItemView = Bundle.main.loadNibNamed("CustomTabItem", owner: nil, options: nil)?.last as! CustomTabItem switch i { case CustomTabbarButtonTag.TabBarItem_First.rawValue: customTabItemView.itemTitle.text = "TabBarItem_First" customTabItemView.topButton.tag = CustomTabbarButtonTag.TabBarItem_First.rawValue customTabItemView.isSelected = false case CustomTabbarButtonTag.TabBarItem_Second.rawValue: customTabItemView.itemTitle.text = "TabBarItem_Second" customTabItemView.topButton.tag = CustomTabbarButtonTag.TabBarItem_Second.rawValue lastSelectedTabItem = customTabItemView customTabItemView.isSelected = true case CustomTabbarButtonTag.TabBarItem_Third.rawValue: customTabItemView.itemTitle.text = "TabBarItem_Third" customTabItemView.topButton.tag = CustomTabbarButtonTag.TabBarItem_Third.rawValue customTabItemView.isSelected = false case CustomTabbarButtonTag.TabBarItem_Fourth.rawValue: customTabItemView.itemTitle.text = "TabBarItem_Fourth" customTabItemView.topButton.tag = CustomTabbarButtonTag.TabBarItem_Fourth.rawValue customTabItemView.isSelected = false cmsTabItem = customTabItemView default: break } customTabItemView.topButton.addTarget(self, action: #selector(tabBarButtonPressed), for: .touchUpInside) stackView.addArrangedSubview(customTabItemView) } } //MARK:- IBActions func tabBarButtonPressed(_ sender: UIButton){ // create global variable lastSelectedTabItem for store last selected tab item and set its isSelected value for manage highlight current selected tabItem lastSelectedTabItem.isSelected = false let customTabItem = sender.superview as! CustomTabItem lastSelectedTabItem = customTabItem lastSelectedTabItem.isSelected = true self.selectedIndex = sender.tag } 
0
source

Source: https://habr.com/ru/post/944188/


All Articles