初学swift5 实现简易自定义tababar

本文是刚学习swift后,第一个练手的项目,主要目的是将学到的swift知识去完成一个简易的自定义tabbar

先看效果


总效果图

然后我们在一层一层看

根据自己的需求,用CGContext 画的背景图
中间的tabBarItem不设置图片,只设置文字
在tabbar上的背景图上插入自定义的控件
这里自定义的控件是button

到这里,总结下就是,
我们自定义的tabbar,根据需求添加一个背景图,然后在插入我们自定义的控件到正确的位置上即可,其他的都沿用原生的tabbar,因为自定义控件会挡住原生tabbaritem,所以需要单独为我们自定义的控件添加点击事件(后面会讲道自定义控件的点击事件)。

代码:

class CustomTabbar: UITabBar {
    private lazy var centerBtn: UIButton = {
        let btn = UIButton.init(type: .custom)
        btn.setImage(UIImage.initWithOriginalMode(named: "tab_diy"), for: .normal)
        btn.setImage(UIImage.initWithOriginalMode(named: "tab_diy_sel"), for: .selected)
        btn.sizeToFit()
        btn.imageEdgeInsets = UIEdgeInsets.init(top: -10, left: 0, bottom: 0, right: 0)
        btn.addTarget(self, action: #selector(clickAtItem), for: .touchUpInside)
        return btn
    }()
    weak open var clickDelegate: CustomTabbarDelegate?

   ...

    override init(frame: CGRect) {
        super.init(frame: frame)
        //   添加背景图
        let backV = UIImageView.init(frame: CGRect.init(x: 0, y: -26, width: ScreenW, height: 75))
        backV.backgroundColor = UIColor.clear
        self.addSubview(backV)

        // 自己绘制的背景图
        let img = drawCustomTabbarBackImg()
        backV.image = img

        // 添加自定义的btn控件
        self.addSubview(centerBtn)
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        // 重新计算自定义btn控件的位置
        centerBtn.frame = CGRect.init(x: ScreenW/5*2, y: -26, width: ScreenW/5, height: 75)
        self.bringSubviewToFront(centerBtn)
    }


    @objc func clickAtItem(btn: UIButton) {
        // btn 点击之后状态给反转下
        btn.isSelected = !btn.isSelected
        // 让代理去实现点击事件。
        clickDelegate?.clickTabbarItem((self, centerBtn))
    }

## 重写hitTest方法,去监听中间按钮点击,目的是为了让凸出的部分点 击也有反应 ##
## 当然你的视图不超出父视图,这个也可以不写 ##

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
        if !self.isHidden, centerBtn.frame.contains(point) {
            return centerBtn
        }
        // 记得把centerbtn 设置成 nomal状态
        centerBtn.isSelected = false
        return super.hitTest(point, with: event)
    }
}
}}

有一个代理的注意点,(毕竟初学swift,还是有必要提一下)

## OC 中代理都是用 weak 修饰 防止循环引用,这里也要遵守 ##
weak open var clickDelegate: CustomTabbarDelegate?

@objc func clickAtItem(btn: UIButton) {
        // btn 点击之后状态给反转下
        btn.isSelected = !btn.isSelected
        // 让代理去实现点击事件。
        clickDelegate?.clickTabbarItem((self, centerBtn))
    }

## :后面的 class,指定只能给class用不能给值类型用 ##
protocol CustomTabbarDelegate: class {
    func clickTabbarItem(_: (Any));
}

接下来就是 tabbarController 里面替换成我们自定义的tabbar了
关键一句就是:

self.setValue(customTab, forKey: "tabBar")
class BaseTabVC: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.customTabbar()

        let temple = (titles: ["首页", "分类", "DIY", "圈子", "我的"], images: ["tab_home", "tab_material", "", "tab_social", "tab_my"])
        let vcs = [HomeVC.init(), MaterialVC.init(), DIYVC.init(), SocialVC.init(), ProfileVC.init()].enumerated().map { (idx, vc) -> UIViewController in
            self.controller(createTabbarItemWith: vc, title: temple.titles[idx], image: temple.images[idx])
            let nav = BaseNavVC.init(rootViewController: vc)
            return nav
        }

        self.viewControllers = vcs
    }

    func customTabbar() {
        let customTab = CustomTabbar.init(frame: CGRect.init(x: 0, y: ScreenH - TabbarH, width: ScreenW, height: TabbarH))
        // 别忘了实现代理
        customTab.clickDelegate = self
        self.setValue(customTab, forKey: "tabBar")

## 这里还是我们熟悉的调整tabbar 上面的一些属性 ##
## 根据我们的需求调整就行 ##

        //调整tabbar 上面横线阴影颜色
        self.tabBar.backgroundImage = UIImage.init()
        self.tabBar.shadowImage = UIImage.init();
        self.tabBar.barTintColor = HEX(hexValue: 0xFFFFFF)
        self.tabBar.tintColor = HEX(hexValue: 0x0D57F6)
        self.tabBar.unselectedItemTintColor = HEX(hexValue: 0x000000)
        self.tabBar.isTranslucent = false
    }
    ...

切换tabBarItem的方法

self.selectedIndex = 2
// 扩展里面, 实现 点击 customTabbar 的代理
extension BaseTabVC: CustomTabbarDelegate {
    func clickTabbarItem(_: (Any)) {
        guard let vc = self.viewControllers?[2] else { return }
## 切换当前tabitem 到我们需要的控制器 ##
        self.selectedIndex = 2
    }
}

写在最后,实现自定义的tabbar 可以有很多种思路,复杂的可以写一个view 替换掉tabbar,然后将系统的tabbar 给隐藏掉,都是可以的,只不过需要实现tabbar所有的功能,会比较繁琐。这个自定义的好处是,整体代码量不多,思路实现也不复杂,主要是不影响原生tabbar的功能。

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

推荐阅读更多精彩内容