I am working on application that is more likely a tabBarController
application. But I can not use the tabBarController
because I need a custom tab
handler at the bottom also I need custom space between items. So I am creating custom tabBarController
.
I would like to know the best approach. Currently my approach is this in way (using storyboard
and iOS6
) :- I took an UIToolbar
on ViewController
which will act as a bottom tab
bar(CustomTabBarViewController). I took ContainerViews
for each tab. When user selects an item on toolbar
, I will show that containerView
.
Please tell me if i am going wrong or guide the best way. Thanks.
You're doing it very very wrong. Do not create a custom view hierarchy when you can just use the default one.
What you want to do is to create a subclass of UITabBarController
and also create a .xib file that will contain your custom tab bar - simply an image and an arbitrary amount of UIButtons (I suppose 5).
Set tags for all of them, just 1-5 tags, you could possibly do it with a custom UIView
subclass, but that would be redundant in this scenario, so it'll be just fetching controls with tags.
Create a subclass of the UITabBarController
. You'll need to have references to all those buttons and also a property to see which button was pressed last, so you could update the UI appropriately. Also assign different images or titles for different control states, I'm using 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 the view controllers (which are all UINavigationController
subclasses in this case) and assign them to your UITabBarController
's subclass as the viewControllers
property.
- (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;
}
Next grab the buttons you've created previously and assign actions to them 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 the processing method:
- (void)processBtn:(UIButton *)sender {
_lastSender = sender;
[self setSelectedViewController:[self.viewControllers objectAtIndex:sender.tag - 1]];
}
And finally override the -setSelectedViewController:
method:
- (void)setSelectedViewController:(UIViewController *)selectedViewController {
if (_lastSender != _btn3) { // check if it's 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'm assuming you're programming with ARC enabled and that you have a class that manages your storyboards, but that's pretty straightforward anyway.
Below code works perfectly in my project.
i have used swift3 version as below :
i added MyTabBar.xib file which contains UIView with 4 buttons.
In xib file, Set Class of UIView. class = "MyTabBar"
Give 4 buttons Tag 1,2,3,4 accordingly..
and below myTabBarController file
myTabBarController.swift code as 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 design custom tabbar as per your need.
Thanks
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With