iOS swift:在标签栏文本中添加kern空间

时间:2018-06-04 08:44:38

标签: ios swift uitabbar

我无法将kern空间添加到标签栏属性文本中。 有问题的UITabBar是一个自定义tabBar,您可以在下面找到代码。

我正在使用“属性键”字典向项目标题添加属性,但我遇到了kern空间的问题。

class ProfileTabBar: UITabBar {

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.setStyle()
}

required override init(frame: CGRect) {
    super.init(frame: frame)
    self.setStyle()
}

func setStyle() {
    self.tintColor = Style.shared.primary1

    // Disable the default border
    self.layer.borderWidth = 0.0
    self.clipsToBounds = true

    // Create a new bottom border
    let bottomLine = CALayer()

    let screenWidth = UIScreen.main.bounds.width
    //let viewForFrame = self.superview ?? self
    //let screenWidth = viewForFrame.bounds.width

    bottomLine.frame = CGRect(x: 0.0, y: self.frame.height - 1, width: screenWidth, height: 2.0)
    bottomLine.backgroundColor = UIColor(red: 235.0/255, green: 235.0/255, blue: 235.0/255, alpha: 1.0).cgColor
    self.layer.addSublayer(bottomLine)

    // Get the size of a single item
    let markerSize = CGSize(width: screenWidth/CGFloat(self.items!.count), height: self.frame.height)

    // Create the selection indicator
    self.selectionIndicatorImage = UIImage().createSelectionIndicator(color: self.tintColor, size: markerSize , lineWidth: 3.0)


    // Customizing the items
    if let items = self.items {
        for item in items {

            item.titlePositionAdjustment = UIOffset(horizontal: 0, vertical: -15)

            let attributes: [NSAttributedStringKey : Any] = [
                NSAttributedStringKey.font: UIFont(name: Style.shared.fontBold.fontName, size: 14) as Any,
                NSAttributedStringKey.kern: NSNumber(value: 1.0)
            ]
            item.setTitleTextAttributes(attributes, for: .normal)

        }
    }

}

除了kern之外,所有属性都有效。我做错了什么?

2 个答案:

答案 0 :(得分:2)

这个问题很旧,答案甚至更老here。看来UITabBarItem的出现会忽略NSAttributedString.Key.kern。这给我们留下了一些选择。

  1. 子类UITabBarItem并不容易,因为UITabBarItem继承自UIBarItem而不是NSObject的{​​{1}}。

  2. 子类UIView可以完成,但是仅需一些精简即可。您必须使用UITabBar而不是UIButton才能应用字距调整。

  3. 您可以在标题中使用Unicode字符添加间距。这真的很容易,并且可能只需几行代码就可以达到您想要的间距。

Unicode spacing

UITabBarItem 1/4 em

U+0020 1/3上午

U+2004 1/4 em

U+2005 1/6 em

U+2006句号“。”的宽度。

U+2008 1/5时(有时1/6时)

您可以像这样U+2009在Swift的String中使用Unicode字符。这意味着我们可以在tabBarItem标题中的所有字符之间插入一个小的空格。像这样:

"\u{2006}"

将其用于我们的tabBarItems:

extension String {
  var withOneSixthEmSpacing: String {
    let letters = Array(self)
    return letters.map { String($0) + "\u{2006}" }.joined()
  }

在视觉上,我们最终得到: enter image description here

代替:

enter image description here

答案 1 :(得分:1)

另一种解决方法是将UITabBarController子类化,并在viewDidLayoutSubviews中设置字距调整。

class FooTabBarController: UITabBarController {

    private var tabBarButtons: [UIControl] {
        tabBar.subviews.compactMap { $0 as? UIControl }
    }

    private var tabBarButtonLabels: [UILabel] {
        tabBarButtons.compactMap { $0.subviews.first { $0 is UILabel } as? UILabel }
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        self.tabBarButtonLabels.forEach {
            if let attributedText = $0.attributedText {
                let mutable = NSMutableAttributedString(attributedString: attributedText)
                mutable.addAttribute(.kern, value: 0.5, range: .init(location: 0, length: mutable.length))
                $0.attributedText = mutable
                $0.sizeToFit()
            }
        }
    }
}

此解决方案的注意事项是:

  1. 它有些脆弱。如果Apple更改了标签栏中的视图结构,即如果他们停止使用UIControl,或者更改了子视图层次结构,则可能会中断。
  2. 效率不是很高,因为必须在每个布局周期都设置字距调整。