swift -- Special custom UITabBar, UITabBarController and UINavigation Controller

Direct picture above:

Custom TabBar

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)
        /// 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{
    override func 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)
            /// 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
                /// 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() {
        let tab = RootTabBar()
        tab.addDelegate = self
        self.setValue(tab, forKey: "tabBar")
        // 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()
            //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

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{
            //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)
            viewController.navigationItem.leftBarButtonItem = UIBarButtonItem.init(customView:backButton)
        super.pushViewController(viewController, animated: true)

//Click Events
    func didBackButton(sender:UIButton){

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

Reprinted please indicate the source, thank you.

Tags: Swift github

Posted on Sun, 02 Jun 2019 16:47:13 -0400 by jwb666