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给星 =。=

转载请注明出处,谢谢。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容

  • 匈牙利两个平原,今日去的是在东南平原上的霍托巴吉国家公园的一个农庄。匈牙利大概有半个山东省那么大,国土面积9万多平...
    远芳阅读 213评论 0 0
  • 妻子爱花。 我喜欢把“她们”通称为我的姑娘们! 家里的角角落落,台台柜柜上凡是有点空地儿的地方都被她的花盆占了去。...
    追梦CEO阅读 123评论 4 2
  • 封面图片里的这栋寝室楼,个子不高(是我把他拍矮了),只有六层。外表也不帅气,灰色的皮肤,倒是挺有朝气。他就像一个憨...
    黑夜中健步如飞的路阅读 823评论 8 3