在Swift中为iOS更改TabBarItem标题字体为粗体

9

我想把选定的选项卡项目的字体加粗。似乎没有效果。有什么问题吗?forState: .Normal 起作用了,但 forState: .Selected 没有任何效果。

let tabBarItem0 = tabBar.items![0] as! UITabBarItem
var selectedImage0 : UIImage = UIImage(named:"ic_tabbar_item_one")!.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)
var fontLight:UIFont = UIFont(name: "HelveticaNeue-UltraLight", size: 12)!
var fontBold:UIFont = UIFont(name: "HelveticaNeue-Bold", size: 12)!

tabBarItem0.image = unselectedImage0
tabBarItem0.selectedImage = selectedImage0
tabBarItem0.title = "Overview"
tabBarItem0.setTitleTextAttributes(
    [
        NSForegroundColorAttributeName: UIColor.whiteColor(),
        NSFontAttributeName: fontLight
    ], forState: .Normal)

tabBarItem0.setTitleTextAttributes(
    [
        NSForegroundColorAttributeName: UIColor.whiteColor(),
        NSFontAttributeName: fontBold
    ], forState: UIControlState.Selected)

你确定你的tabBarItem状态已经变成了“Selected”吗? - Lucas Huang
不,我不是。我该如何检查呢? - Thomas Kremmel
1
你找到解决方案了吗?我也遇到了同样的问题。 - FedeH
我找到的最佳解决方案在这里: https://dev59.com/4l8e5IYBdhLWcg3w6d0_ - Mattias Almén
7个回答

6

找到解决方案 (Swift 3, XCode 8.1)

  1. 在Storyboard中为每个UITabBarItem设置唯一的标记(Tag):选择每个选项卡,转到其“属性检查器”并在“Tag”字段中给每个选项卡一个唯一的数字(不要使用0,我使用了1到4)。

    这为我们后面的工作做好了准备,以识别哪个选项卡被按下。


  1. 创建UITabBarController的新子类,然后将其分配:文件-> 新建文件-> iOS Cocoa Touch->创建UITabBarController的子类。在“Identity Inspector”下将新的.swift文件分配给您的UITabBarController。

    我们需要在UITabBarController中进行自定义逻辑。


  1. 创建UITabBarItem的新子类,将同一个文件分配给所有UITabBarItems:文件-> 新建文件-> iOS Cocoa Touch->创建UITabBarItem的子类,并将同一个文件分配给所有选项卡。

    我们需要在选项卡栏目中共享自定义逻辑。

  1. Add this code to your UITabBarItem subclass, it sets up the initial state (primary tab bold, the rest unselected) and will allow for programmatic tab changes as well:

    class MyUITabBarItemSubclass: UITabBarItem {
    
        //choose initial state fonts and weights here
        let normalTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightRegular) 
        let selectedTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightBold)
    
        //choose initial state colors here
        let normalTitleColor = UIColor.gray 
        let selectedTitleColor = UIColor.black
    
        //assigns the proper initial state logic when each tab instantiates 
        override func awakeFromNib() {
            super.awakeFromNib()
    
            //this tag # should be your primary tab's Tag* 
            if self.tag == 1 { 
                self.setTitleTextAttributes([NSFontAttributeName: selectedTitleFont, NSForegroundColorAttributeName: selectedTitleColor], for: UIControlState.normal)
            } else {
                self.setTitleTextAttributes([NSFontAttributeName: normalTitleFont, NSForegroundColorAttributeName: normalTitleColor], for: UIControlState.normal)
            }
    
        }
    
    }
    

在这里,我们设置了初始状态,以便在应用程序打开时正确设置选项卡,下一个子类将处理物理选项卡按下。


  1. Add this code to your UITabBarController subclass, it's the logic for assigning the correct states as you press on the tabs.

    class MyUITabBarControllerSubclass: UITabBarController {
    
        //choose normal and selected fonts here
        let normalTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightRegular)
        let selectedTitleFont = UIFont.systemFont(ofSize: 12, weight: UIFontWeightBold)
    
        //choose normal and selected colors here
        let normalTitleColor = UIColor.gray
        let selectedTitleColor = UIColor.black
    
    
        //the following is a delegate method from the UITabBar protocol that's available 
        //to UITabBarController automatically. It sends us information every
        //time a tab is pressed. Since we Tagged our tabs earlier, we'll know which one was pressed,
        //and pass that identifier into a function to set our button states for us
    
        override func tabBar(_ tabBar: UITabBar, didSelect item: UITabBarItem) {
            setButtonStates(itemTag: item.tag)
        }
    
    
        //the function takes the tabBar.tag as an Int
        func setButtonStates (itemTag: Int) {
    
            //making an array of all the tabs
            let tabs = self.tabBar.items
    
            //looping through and setting the states
            var x = 0
            while x < (tabs?.count)! {
    
                if tabs?[x].tag == itemTag {
                    tabs?[x].setTitleTextAttributes([NSFontAttributeName: selectedTitleFont, NSForegroundColorAttributeName: selectedTitleColor], for: UIControlState.normal)
                } else {
                    tabs?[x].setTitleTextAttributes([NSFontAttributeName: normalTitleFont, NSForegroundColorAttributeName: normalTitleColor], for: UIControlState.normal)
                }
    
                x += 1
    
            }
    
        }
    
    }
    

看起来这很麻烦,因为某种原因选项卡没有识别状态变化为“.Selected”。我们只能通过使用“.Normal”状态来检测状态变化-基本上是自己检测。


  1. 您可以通过编程方式更改选项卡并仍然检测到状态更改...如果有人感兴趣,我稍后会更新,请问一下。

希望这可以帮助你!


2
当我尝试更改所选项的字体时,遇到了相同的问题。看起来,titleTextAttributes的字体参数仅在将其设置为正常状态时有用。这就是为什么我实现了UITabBarControllerDelegate,以更新当前选定项目的属性。您应该在UITabBarController的loadView()方法之后调用updateSelection()方法。或者,您可以在重写的selectedItem setter中调用updateSelection()方法。
extension TabBarController: UITabBarControllerDelegate {

  func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
    updateSelection()
  }

  func updateSelection() {
    let normalFont = Fonts.Lato.light.withSize(10)
    let selectedFont = Fonts.Lato.bold.withSize(10)
    viewControllers?.forEach {
      let selected = $0 == self.selectedViewController
      $0.tabBarItem.setTitleTextAttributes([.font: selected ? selectedFont : normalFont], for: .normal)
    }
  }

}

2
在 iOS 11.4 上无法正常工作,状态混乱。 - damjandd

2

构建设置\Swift语言版本: 4.1

通用\部署目标: 10.3

import UIKit

class FirstViewController: UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    let attrsNormal = [NSAttributedStringKey.foregroundColor : UIColor.black,
                 NSAttributedStringKey.font : UIFont(name: "Arial", size: 14)!]
    UITabBarItem.appearance().setTitleTextAttributes(attrsNormal,
                                                     for: UIControlState.normal)

    let attrsSelected = [NSAttributedStringKey.foregroundColor : UIColor.red,
                       NSAttributedStringKey.font : UIFont(name: "Arial", size: 14)!]
    UITabBarItem.appearance().setTitleTextAttributes(attrsSelected,
                                                     for: UIControlState.selected)
  }
  ...
}

2
UITabBarItem.appearance().setTitleTextAttributes(
        [NSFontAttributeName: UIFont(name:"your_font_name", size:11)!, 
            NSForegroundColorAttributeName: UIColor(rgb: 0x929292)], 
        forState: .Normal)

2
这对于.selected状态并没有改变字体。 - AydinAngouti

2

当我尝试使用UITabBarItem更改所选选项卡的字体时,但它无法正常工作。建议采用委托来在选项卡更改时得到通知。我只是把这些部分组合在一起。


private class MyTabBarController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        delegate = self
    }

    override func setViewControllers(_ viewControllers: [UIViewController]?, animated: Bool) {
        super.setViewControllers(viewControllers, animated: animated)
        updateTabBarAppearance()
    }
}

extension MyTabBarController: UITabBarControllerDelegate {

    public func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        updateTabBarAppearance()
    }

    func updateTabBarAppearance() {
        self.tabBar.tintColor = .red
        let unselectedLabelFont = UIFont.systemFont(ofSize: 18, weight: .regular)
        let selectedLabelFont = UIFont.systemFont(ofSize: 20, weight: .semibold)
        let labelColor = UIColor.init(red: 38/255.0, green: 38/255.0, blue: 38/255.0, alpha: 1.0)
        let selectedIconColor = UIColor.init(red: 8/255.0, green: 8/255.0, blue: 8/255.0, alpha: 1.0)

        viewControllers?.forEach {
            let isSelected = $0 == self.selectedViewController
            let selectedFont = isSelected ? selectedLabelFont : unselectedLabelFont
            $0.tabBarItem.setTitleTextAttributes([.font: selectedFont, .foregroundColor: labelColor], for: .normal)

        }
    }
} 

嗨,@HapiNguyen!你能否编辑你的帖子,解释一下你的解决方案是如何回答OP的问题的呢? - otolock
嗨@otolock,没问题,我希望这已经足够清楚了。 - Hapi_Nguyen

1
问题在于 tabBarItem0 的状态没有被改变为 Selected。因为这是一个表示 UITabBar 单个元素的 UITabBarItem,所以你不能直接使用 UITabBarItem API 更改其状态。你需要通过赋值 selectedItem 来改变它的状态。
这些信息可以从文档中获取,我建议所有程序员都要具备这样的技能。希望这会有所帮助。

setItems 是将项目设置到选项卡栏中,当您想要添加、删除或重新排序选项卡中的项目时使用。就我理解而言,这与选择状态无关:https://goo.gl/LfEIKH - Thomas Kremmel
我刚刚更新了答案。你应该将其分配给 UITabBarselectedItem 属性。@ThomasKremmel - Lucas Huang

1
要设置TitleTextAttribute,应该使用appearance代理,如下所示:[UIBarItem appearance]

他在询问为什么外观没有改变,而不是询问如何改变外观。 - Lucas Huang
是的,我知道他在问什么。我相信原因是它没有被正确设置。 - rmp
根据文档:“在iOS v5.0及更高版本中,您可以使用UIBarItem声明的外观选择器设置项目标签文本属性来自定义选项卡栏的外观。” - rmp
代码的最后两行是不正确的,如果它们是 OP 的代码,那么就可以工作,也不会有这篇文章。此外,在 OP 中并没有说明它只适用于单个选项卡,只是在选择选项卡时。不将粗体选定状态应用于所有选项卡似乎很奇怪。让我们就此达成不同意见,因为这并不具有建设性。 - rmp
我甚至尝试使用UIBarItemappearance代理。相同的效果->没有结果。我开始认为这是模拟器的错误。将在真实硬件上尝试。UIBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: UIColor.whiteColor(), NSFontAttributeName: fontBold], forState: UIControlState.Selected) - Thomas Kremmel
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接