Which is the best approach for creating custom tab bar controller?

后端 未结 4 1662
Happy的楠姐
Happy的楠姐 2021-02-03 11:25

I am working on application that is more likely a tabBarController application. But I can not use the tabBarController because I need a custom ta

相关标签:
4条回答
  • 2021-02-03 12:20

    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).

    enter image description here

    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.

    0 讨论(0)
  • 2021-02-03 12:24

    For ios 9.0+ use UIStackView in Horizontal direction and create a xib and named it CustomTabBarView

    CustomTabBarView.Xib

    Create Another View CustomTabBarItem.

    CustomTabBarItem.xib

    create CustomTabBarItem.swift file for implement functionality of TabItem

    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 Implement 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 讨论(0)
  • 2021-02-03 12:27

    Here are the step you need to follow in order to make the following view :-

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

    2: Now add Five Tab to this UITabbarController .

    3: Add five seperate UINavigationController to each Tab individually.

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

    5: Create a Custom Tabbar now :

    5.1 : One of the way of creating custom Tabbar is to take a UIView of Tabbar height and add UIButtons as Tab to the Tabbar.

    6: Add the Custom tabBar on to the MainWindow . On choosing various button on your custom tabbar change the setSelectedIndex of your application UITabbarController.

    0 讨论(0)
  • 2021-02-03 12:28

    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

    0 讨论(0)
提交回复
热议问题