美文网首页程序员
如何使用Swift自定义TabBarController

如何使用Swift自定义TabBarController

作者: wolf_吴郎 | 来源:发表于2017-03-21 09:56 被阅读0次

    TabBarController是项目主要框架结构, 一般来说系统自带的TabBarController已足够使用, 但是要实现一些产品的需求,有时候就需要我们自定义一个TabBarController,本篇文章将为您讲述如何使用Swift自定义TabBarController.顺便附上Demo地址

    github.com/15395401361/LFTabBarContoller

    首先:定制TabBar上面的按钮。

    //

    //  LFCustomButtonItem.swift

    //  LFTabBarDemo

    //

    //  Created by 吴林丰 on 2017/3/20.

    //  Copyright © 2017年 吴林丰. All rights reserved.

    //

    import UIKit

    class LFCustomButtonItem: UIButton {

    // MARK: - 页面所用属性

    private let itemWH = 40  //item的大小

    private let itemTitleColor = UIColor.colorWithHexString(hex: "7b7b7b") //item  中默认的字体颜色

    private let selectedItemTitleColor = UIColor.colorWithHexString(hex: "e2231a")  //item中被选中是字体的颜色

    private let itemTitleFont = UIFont.systemFont(ofSize: 10) //item中字体的大小

    private let badgeValueViewImageName = "badge_one@2x.png" //提醒背景图片

    private let badgeValueViewImageNameMore = "badge_more@2x.png" //更多背景提醒

    private let badgeValueFont = UIFont.systemFont(ofSize: 12)

    private let badgeValueColor = UIColor.white

    private var badgeValueViewWH:CGFloat{

    get{

    //            return CGFloat(itemWH) * 0.15 //如果只是红点提示,则返回此大小

    return CGFloat(itemWH) * 0.45  //如果显示数字,则返回这个大小

    }

    }

    private let KSImageScale:CGFloat = 1

    // MARK: - 懒加载红点

    lazy var badgeValueView:UIButton = {

    let x:CGFloat = self.frame.size.width/2+10

    let y:CGFloat = 5

    //        let x:CGFloat = self.frame.size.width/2+5

    //        let y:CGFloat = 3 只是小红点提示的时候,常量值为这个

    let badgeValueView:UIButton = UIButton.init(frame: CGRect.init(origin: CGPoint.init(x: x, y: y), size: CGSize.init(width: self.badgeValueViewWH, height: self.badgeValueViewWH)))

    badgeValueView.setBackgroundImage(UIImage.init(named: self.badgeValueViewImageName), for: .normal)

    badgeValueView.setTitleColor(self.badgeValueColor, for: UIControlState.normal)

    badgeValueView.adjustsImageWhenHighlighted = false

    badgeValueView.isHidden = true

    badgeValueView.titleLabel?.font = UIFont.systemFont(ofSize: 12)

    return badgeValueView

    }()

    // MARK: - 初始化self

    init(_ frame: CGRect,_ norImage:String,_ selectImage:String,_ titile:String) {

    super.init(frame: frame)

    //顶部图片

    self.imageView?.contentMode = .center

    self.setImage(UIImage.init(named: norImage), for: .normal)

    self.setImage(UIImage.init(named: selectImage), for: .selected)

    self.setImage(UIImage.init(named: norImage), for: .highlighted)

    //设置文字

    self.titleLabel?.textAlignment = .center

    self.setTitle(titile, for: .normal)

    self.setTitleColor(itemTitleColor, for: .normal)

    self.setTitleColor(itemTitleColor, for: .highlighted)

    self.setTitleColor(selectedItemTitleColor, for: .selected)

    self.titleLabel?.font = itemTitleFont

    self.addSubview(self.badgeValueView)

    }

    // MARK: - 设置提醒小红点的数量

    func setItemBadgeNumber(_ number:Int){

    if number != 0 {

    if  self.badgeValueView.isHidden == true {

    self.badgeValueView.isHidden = false

    }

    /**

    实现红点及数字提醒

    */

    let tabBadgeNum:String = number > 99 ? "...":"\(number)"

    self.badgeValueView.setTitle(tabBadgeNum, for: .normal)

    let tabBadgeStr:String = "\(number)"

    let longImage:UIImage = UIImage.resizableImage(imageName: badgeValueViewImageName)

    self.badgeValueView.setBackgroundImage(longImage, for: .normal)

    var newframe:CGRect = self.badgeValueView.frame

    if (tabBadgeStr as NSString).length > 1 {

    newframe.size.width = badgeValueViewWH + 4

    self.badgeValueView.frame = newframe

    }else{

    newframe.size.width = badgeValueViewWH

    self.badgeValueView.frame = newframe

    }

    /**

    只实现红点提醒,不实现数字提醒

    同上方的方法二者选一

    */

    //            self.badgeValueView.setBackgroundImage(UIImage.init(named: "TabBarEdgeImage"), for: .normal)

    }else{

    self.badgeValueView.isHidden = true

    }

    }

    //重写系统方法,设置按钮内部图片和文字的位置

    override func imageRect(forContentRect contentRect: CGRect) -> CGRect {

    let W:CGFloat = contentRect.size.width

    let H:CGFloat = contentRect.size.height * KSImageScale

    return CGRect.init(x: 0, y: -5, width: W, height: H)

    }

    override func titleRect(forContentRect contentRect: CGRect) -> CGRect {

    let W:CGFloat = contentRect.size.width

    let H:CGFloat = contentRect.size.height * KSImageScale

    let Y:CGFloat = contentRect.size.height - H

    return CGRect.init(x: 0, y: Y+15, width: W, height: H)

    }

    //这个是用于Storyboard 的。苹果由于主推SB,所以要求必须实现此方法

    required init?(coder aDecoder: NSCoder) {

    fatalError("init(coder:) has not been implemented")

    }

    }

    第二步,继承TabBarController,开始定制自己项目的TabBarController,并编写项目中所要用到的方法。

    //

    //  LFCustomTabBarController.swift

    //  LFTabBarDemo

    //

    //  Created by 吴林丰 on 2017/3/20.

    //  Copyright © 2017年 吴林丰. All rights reserved.

    //

    import UIKit

    class LFCustomTabBarController: UITabBarController {

    var currentSelectedIndex:NSInteger? //当前选中的button的index

    var buttons = [LFCustomButtonItem]()

    let ScreenWidth = kScreenWidth

    lazy var objectNavis:[UINavigationController] = {

    var navis = [UINavigationController]()

    navis = self.viewControllers as! [UINavigationController]

    return navis

    }()

    override func viewDidLoad() {

    super.viewDidLoad()

    }

    override func viewWillAppear(_ animated: Bool) {

    super.viewWillAppear(animated)

    self.customTabBar()

    }

    func customTabBar(){

    //初始化TabBar上的Item数量和Item上的标题,图片等等

    let normalImageArr = NSArray.init(array: ["out-call","patientsNormal","personalCenterNormal"])

    let selectedImageArray = NSArray.init(array: ["out-callSelected","patientsSelected","personalCenterSelected"])

    let titleArr = NSArray.init(array: ["首页","联系人","个人中心"])

    let viewCount:Int = (self.viewControllers?.count)! > 5 ? 5:(self.viewControllers?.count)!

    let _width:CGFloat = kScreenWidth / CGFloat(viewCount)

    let _height:CGFloat = self.tabBar.frame.size.height

    for i in 0 ..< (self.viewControllers?.count)!{

    let btn:LFCustomButtonItem = LFCustomButtonItem.init(CGRect.init(x: CGFloat(i) * _width, y: 0, width: _width, height: _height), normalImageArr[i] as! String, selectedImageArray[i] as! String, titleArr[i] as! String)

    btn.addTarget(self, action: #selector(selectedTab(_:)), for: UIControlEvents.touchUpInside)

    btn.tag = i

    self.buttons.append(btn)

    self.tabBar.addSubview(btn)

    }

    //默认选中第一个页面

    if self.buttons.count > 0 {

    self.buttons[0].isSelected = true

    self.selectedTab(self.buttons[0])

    }

    }

    // MARK - 设置消息数量

    //设置消息数

    func setBadgeNumber(_ number:NSInteger,_ index:NSInteger){

    let  buttonItem:LFCustomButtonItem = self.buttons[index]

    buttonItem.setItemBadgeNumber(number)

    }

    func pushToHome(){

    for bt in self.buttons {

    if bt.tag == 0 {

    bt.isSelected = true

    }else{

    bt.isSelected = false

    }

    }

    self.selectedIndex = 0

    let nav:UINavigationController = self.objectNavis[0]

    nav.popToRootViewController(animated: true)

    }

    //其他页面调用选择按钮

    func selectedTab(_ button:UIButton){

    if self.currentSelectedIndex == button.tag{

    return

    }

    for bt in self.buttons{

    if bt == button {

    bt.isSelected = true

    }else{

    bt.isSelected = false

    }

    }

    self.currentSelectedIndex = button.tag

    self.selectedIndex = self.currentSelectedIndex!

    //选中一级界面

    if self.selectedIndex != 0 && (self.viewControllers?.count)! > self.selectedIndex  {

    /**

    注意此处的跳转

    由于系统的TabBarController上的viewCoutrollers 默认为继承的是UIViewController

    所以,如果使用自定义的导航栏去加载ViewControllers作为TabBarControlelr的viewCoutrollers时

    此处需要进行类型转换,从而顺利进行跳转。

    */

    if self.objectNavis.count > 0{

    //此处需要将其转为具有导航功能的navigationController

    (self.selectedViewController as! UINavigationController).popToRootViewController(animated: true)

    }

    }

    }

    override func didReceiveMemoryWarning() {

    super.didReceiveMemoryWarning()

    // Dispose of any resources that can be recreated.

    }

    }

    1. 如何进行页面切换

    自定义的TabBarController继承自系统, 所以还是直接用系统的selectedIndex属性来实现, 

    2. 自定义的几个Button如何只选中一个, 以及选中状态的切换?

    定义一个currentSelectedIndex,标示表示选中的button按钮。

    3.如何使用

    通过上面的封装可以实现传入数据源,初始化tabBarController,并且支持角标及小红点,很方便在今后项目中调用.喜欢的话,给个星星,你们的支持就是我们笔者的动力。谢谢。✨

    相关文章

      网友评论

        本文标题:如何使用Swift自定义TabBarController

        本文链接:https://www.haomeiwen.com/subject/mcmwnttx.html