Direct picture above:

I believe you've seen this special TabBar. In fact, the essence is still four UITabBarButtons, plus a custom Button, so TabBar still follows the system response. Personally, I think this is the most reasonable way, but there's also a clever way to do it. It's essentially five UITabBarButtons, with the middle one occupying a seat, and then covering it all with Button. Personally, I think this layout has already lost, and then it is unreasonable. What I'm going to talk about is modifying the location of UITabBarButton, customizing a TabBar and rewriting some methods.
Customize UITabBar
Let's just talk about the code. If the amount of code is small, we'll talk about it separately.
/// Upload button click agent protocol RootTabBarDelegate:NSObjectProtocol { func addClick() } /// Customize tabbar and modify the location of UITabBarButton class RootTabBar: UITabBar { weak var addDelegate: RootTabBarDelegate? private lazy var addButton:UIButton = { return UIButton() }() override init(frame: CGRect) { super.init(frame: frame) addButton.setBackgroundImage(UIImage.init(named: "Icon_add"), for: .normal) addButton.addTarget(self, action: #selector(RootTabBar.addButtonClick), for: .touchUpInside) self.addSubview(addButton) /// tabbar setting background color // self.shadowImage = UIImage() self.backgroundImage = UIColor.creatImageWithColor(color: UIColor.white) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func addButtonClick(){ if addDelegate != nil{ addDelegate?.addClick() } } override func layoutSubviews() { super.layoutSubviews() let buttonX = self.frame.size.width/5 var index = 0 for barButton in self.subviews{ if barButton.isKind(of: NSClassFromString("UITabBarButton")!){ if index == 2{ /// Setting the Add Button Position addButton.frame.size = CGSize.init(width: (addButton.currentBackgroundImage?.size.width)!, height: (addButton.currentBackgroundImage?.size.height)!) addButton.center = CGPoint.init(x: self.center.x, y: self.frame.size.height/2 - 18) index += 1 } barButton.frame = CGRect.init(x: buttonX * CGFloat(index), y: 0, width: buttonX, height: self.frame.size.height) index += 1 } } self.bringSubview(toFront: addButton) } /// Rewrite the hitTest method, listen for the button click to make the highlighted tabbar part respond to the click override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { /// Determine whether it is the root controller if self.isHidden { /// tabbar hiding is not handled in the home page system return super.hitTest(point, with: event) }else{ /// Converting Money Touch Points to Buttons to Generate New Points let onButton = self.convert(point, to: self.addButton) /// Determine whether the new point is on the button if self.addButton.point(inside: onButton, with: event){ return addButton }else{ /// No System Processing on the Button return super.hitTest(point, with: event) } } } }
The main points are as follows: lazy loading of Button, layoutSubviews rewriting UITabBarButton location, rewriting hitTest method and listening for button clicks
This is the first step in TabBar customization, followed by the UITabBarController section.
Customize UITabBarController
Replace the custom TabBar with the default and follow the proxy
let tabBarNormalImages = ["TabBar0_Normal","TabBar0_Normal","TabBar0_Normal","TabBar0_Normal"] let tabBarSelectedImages = ["TabBar0_Selected","TabBar0_Selected","TabBar0_Selected","TabBar0_Selected"] let tabBarTitles = ["home page","news","function","My"] override func viewDidLoad() { super.viewDidLoad() let tab = RootTabBar() tab.addDelegate = self self.setValue(tab, forKey: "tabBar") self.setRootTabbarConntroller() // Do any additional setup after loading the view. }
Agent Method and UITabBarController's Self-Definition
/// Upload button execution method func addClick() { print("add succeed") } func setRootTabbarConntroller(){ var vc : UIViewController? for i in 0..<self.tabBarNormalImages.count { //Create the root controller switch i { case 0: vc = ViewController() case 1: vc = UIViewController() case 2: vc = UIViewController() case 3: vc = UIViewController() default: break } //Creating Navigation Controller let nav = RootNavigationController.init(rootViewController: vc!) //1. Create tabbarItem let barItem = UITabBarItem.init(title: self.tabBarTitles[i], image: UIImage.init(named: self.tabBarNormalImages[i])?.withRenderingMode(.alwaysOriginal), selectedImage: UIImage.init(named: self.tabBarSelectedImages[i])?.withRenderingMode(.alwaysOriginal)) //2. Change font color barItem.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.colorWithHexString("cccccc")], for: .normal) barItem.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.colorWithHexString("21d1c1")], for: .selected) //Setting titles vc?.title = self.tabBarTitles[i] //Setting Root Controller vc?.tabBarItem = barItem //Add to the current controller self.addChildViewController(nav) } }
Finally is the UI Navigation Controller's customization, project needs. But now most of them need to customize UI Navigation Controller, and these three together are a complete custom root controller!
Customize UI Navigation Controller
Setting the background color and title of the navigation bar
func defaultSetting(){ //Background color and title setting of navigation bar self.navigationBar.barStyle = UIBarStyle.default self.navigationBar.barTintColor = UIColor.white self.navigationBar.isTranslucent = false self.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName : UIColor.colorWithRGB(r:51/255, g: 51/255, b: 51/255, alpha: 1),NSFontAttributeName:UIFont.systemFont(ofSize:17)] UIApplication.shared.statusBarStyle = UIStatusBarStyle.default }
Rewrite pushViewController, because the return buttons of the project are literal, so they are defined directly in the method. I also tried UIBarButtonItem.appearance(), but I couldn't point out the grammar or see the method. I don't know if it's swift or not. I hope Daniel knows that he can point me out and communicate with me.
override func pushViewController(_ viewController: UIViewController, animated: Bool) { if self.childViewControllers.count > 0{ viewController.tabBarController?.tabBar.isHidden=true //Navigation Bar Return Button Customization let backButton = UIButton(frame:CGRect.init(x:15, y: 2, width: 30, height: 40)) backButton.imageEdgeInsets = UIEdgeInsetsMake(0,10,0,10) backButton.setImage(UIImage.init(named:"Icon_back"), for: UIControlState.normal) backButton.addTarget(self, action:#selector(self.didBackButton(sender:)), for: UIControlEvents.touchUpInside) backButton.sizeToFit() viewController.navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView:backButton) } super.pushViewController(viewController, animated: true) } //Click Events func didBackButton(sender:UIButton){ self.popViewController(animated:true) }
I wrote a separate Color_extension in the code, which is about the color hexadecimal system and so on, and then I wanted to see the project directly and download it from Githb.—— BartRootTaabbarViewController
If it's helpful to you, you can collect Github for Star=. =