Osheep

时光不回头,当下最重要。

swift——特殊的自定义UITabBar,UITabBarController和UINavigationController

直接上图:

《swift——特殊的自定义UITabBar,UITabBarController和UINavigationController》

自定义TabBar

相信大家也看过这种特殊的TabBar,其实本质还是4个UITabBarButton,加上一个自定义Button,这样子TabBar还是遵循系统响应。个人认为这样子是最合理的,但是这样也有那种取巧的办法,就是本质上是5个UITabBarButton,中间那个占个位子,然后用Button全部覆盖它。个人觉得这样子布局就已经输了,然后也不合理。我要讲的这种就是修改UITabBarButton的位置,自定义一个TabBar并重写一些方法。

自定义UITabBar

还是代码说话把,代码量不大,就不分开讲了

/// 上传按钮点击代理
protocol RootTabBarDelegate:NSObjectProtocol {
    func addClick()
}

/// 自定义tabbar,修改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设置背景色
//        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{
                    /// 设置添加按钮位置
                    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)
    }
    
    /// 重写hitTest方法,监听按钮的点击 让凸出tabbar的部分响应点击
    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        
        /// 判断是否为根控制器
        if self.isHidden {
            /// tabbar隐藏 不在主页 系统处理
            return super.hitTest(point, with: event)
            
        }else{
            /// 将单钱触摸点转换到按钮上生成新的点
            let onButton = self.convert(point, to: self.addButton)
            /// 判断新的点是否在按钮上
            if self.addButton.point(inside: onButton, with: event){
                return addButton
            }else{
                /// 不在按钮上 系统处理
                return super.hitTest(point, with: event)
            }
        }
    }
}

主要就几点:懒加载Button,layoutSubviews重写UITabBarButton位置,重写hitTest方法并监听按钮的点击

这是第一步TabBar的自定义,然后是UITabBarController的部分

自定义UITabBarController

将自定义的TabBar替换掉默认的,并且遵循代理

let tabBarNormalImages = ["TabBar0_Normal","TabBar0_Normal","TabBar0_Normal","TabBar0_Normal"]
    let tabBarSelectedImages = ["TabBar0_Selected","TabBar0_Selected","TabBar0_Selected","TabBar0_Selected"]
    let tabBarTitles = ["首页","消息","功能","我的"]

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

代理方法和UITabBarController的自定义

/// 上传按钮执行方法
    func addClick() {
        
        print("add succeed")
    }
    
    func setRootTabbarConntroller(){
        
        var vc : UIViewController?
        
        for i in 0..<self.tabBarNormalImages.count {
            
            //创建根控制器
            switch i {
            case 0:
                vc = ViewController()
            case 1:
                vc = UIViewController()
            case 2:
                vc = UIViewController()
            case 3:
                vc = UIViewController()
            default:
                break
            }
            
            //创建导航控制器
            let nav = RootNavigationController.init(rootViewController: vc!)
            
            //1.创建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.更改字体颜色
            barItem.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.colorWithHexString("cccccc")], for: .normal)
            barItem.setTitleTextAttributes([NSForegroundColorAttributeName : UIColor.colorWithHexString("21d1c1")], for: .selected)
            
            //设置标题
            vc?.title = self.tabBarTitles[i]
            
            //设置根控制器
            vc?.tabBarItem = barItem
            
            //添加到当前控制器
            self.addChildViewController(nav)
        }
    }

最后是UINavigationController的自定义,项目需要。但是现在大多数都是需要自定义UINavigationController,而且这三者合在一起才是一个完整的自定义根控制器!

自定义UINavigationController

设置导航栏背景色和标题

func defaultSetting(){
        
        //导航栏的背景色与标题设置
        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
    }

重写pushViewController,因为项目的返回按钮都是没有文字的,所以直接在方法里去定义。也有去尝试UIBarButtonItem.appearance()但是后面就点不出来语法,也看不到方法。不知道是不是swift的原因,希望有大牛知道可以指点下我,一同交流。

override func pushViewController(_ viewController: UIViewController, animated: Bool) {
        
        if self.childViewControllers.count > 0{
            viewController.tabBarController?.tabBar.isHidden=true
            
            //导航栏返回按钮自定义
            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)
    }

//点击事件
    func didBackButton(sender:UIButton){
        self.popViewController(animated:true)
    }

代码里面有关于color的16进制等等扩展方法我是单独写了一个Color_extension,工程里有,然后想直接看工程可以去Githb下载——BartRootTaabbarViewController

如果对你有帮助,可以点赞收藏Github给星 =。=

转载请注明出处,谢谢。
点赞