iOS Swift实现字体加粗、倾斜、加粗倾斜和正常的切换,而不改变其他属性

17

我很惊讶,仅仅设置现有字体的加粗和斜体在Swift中如此复杂。

我希望通过在字体类上添加以下方法来简化事情。

我希望将以下方法添加到已经设置了字体系列和字号的现有字体中。 我需要保留这些设置,只更改以下内容。

setBold:应保留斜体

setItalic:应保留加粗

setBoldItalic

setNormal:删除加粗和斜体

removeBold:应保留斜体

removeitalic:应保留加粗

我尝试了下面的代码,并且使用fontDescriptorWithSymbolicTraits感觉像是一场噩梦。

是否有更简单的方法可以用几行代码实现这些功能呢?

extension UIFont
{
    var isBold: Bool
    {
        return fontDescriptor().symbolicTraits.contains(.TraitBold)
    }

    var isItalic: Bool
    {
        return fontDescriptor().symbolicTraits.contains(.TraitItalic)
    }

    func setBold() -> UIFont
    {
        var fontDescriptorVar: UIFontDescriptor
        if(isBold){
            return self
        }
        else
        {
            fontDescriptorVar = fontDescriptor().fontDescriptorWithSymbolicTraits(.TraitBold)
        }
        return UIFont(descriptor: fontDescriptorVar, size: 0)
    }

    func setItalic()-> UIFont
    {
        var fontDescriptorVar: UIFontDescriptor
        if(isItalic) {
            return self
        }
        else
        {
            fontDescriptorVar = fontDescriptor().fontDescriptorWithSymbolicTraits(.TraitItalic)
        }
        return UIFont(descriptor: fontDescriptorVar, size: 0)
    }

    func setBoldItalic()-> UIFont
    {
        let fontDescriptorVar = fontDescriptor().fontDescriptorWithSymbolicTraits(UIFontDescriptorSymbolicTraits(arrayLiteral: .TraitBold, .TraitItalic))
        return UIFont(descriptor: fontDescriptorVar, size: 0)
    }

    // Things I need are

    // To set back to normal

    func setNormal()-> UIFont
    {

    }

    // Remove only bold if it's both bold and Italic

    func removeBold()-> UIFont
    {

    }

    // Remove only italic if it's both bold and Italic

    func removeitalic()-> UIFont
    {

    }
}

我不想使用需要输入字体大小和字体样式的功能:

UIFont(name "namFontFamily", size: 16)

UIFont.systemFontOfSize(16, weight: UIFontWeightLight)

我到处搜索,但没有找到符合我的需求的简单解决方案。


我认为检查字体族非常重要,因为并不是所有字体都有粗体和斜体形式,你是使用默认字体还是添加了新字体? - reojased
我有自己的字体族列表,其中包括粗体和斜体。此外,文本颜色也与字体一起出现。 - Sujay U N
大多数字体都有“Bold”或“Italic”后缀,因此如果您的字体名称与此模式匹配,可能可以通过它们的名称构建字体。 - Ali Kıran
我的方法应该与字体系列无关,它应该像CSS中的加粗一样。因为我正在尝试创建一个通用的方法以供长期使用。 - Sujay U N
6个回答

19

你说你希望保留其他特征,因此你可能需要修改代码中的一些方法:

func setBold() -> UIFont
{
    if isBold {
        return self
    } else {
        var symTraits = fontDescriptor().symbolicTraits
        symTraits.insert([.TraitBold])
        let fontDescriptorVar = fontDescriptor().fontDescriptorWithSymbolicTraits(symTraits)
        return UIFont(descriptor: fontDescriptorVar, size: 0)
    }
}

setItalic()setBoldItalic() 也是如此。

因此,removeBold() 应该像这样:

func removeBold()-> UIFont
{
    if !isBold {
        return self
    } else {
        var symTraits = fontDescriptor().symbolicTraits
        symTraits.remove([.TraitBold])
        let fontDescriptorVar = fontDescriptor().fontDescriptorWithSymbolicTraits(symTraits)
        return UIFont(descriptor: fontDescriptorVar, size: 0)
    }
}

removeItalic()将类似。

但是我不确定setNormal()。你想要删除所有属性,还是只想要删除斜体和粗体?也许你可以按照自己的喜好进行操作。


1
这正是我在寻找的,非常感谢。你真的救了我的一天 :-) - Sujay U N
@ReimondHill,请解释一下“不起作用”的含义。就我测试的情况来看,我的针对Swift 4.2翻译的代码在Xcode 10和iPhone模拟器12.0上都能正常运行。 - OOPer

7
这些功能应该已经内置在Swift中了,但我希望它们能在未来的版本中添加进来。对于那些想要在Swift中设置粗体、斜体等等并且不想像我一样整夜都在寻找简单解决方案的人来说,这篇文章非常适合你。
这个库有以下特点:
- isBold - isItalic - setBold:应保留斜体 - setItalic:应保留粗体 - setBoldItalic - setNormal:同时去除粗体和斜体 - desetBold:应保留斜体 - desetItalic:应保留粗体 - toggleBold - toggleItalic
extension UIFont
{
    var isBold: Bool
    {
        return fontDescriptor().symbolicTraits.contains(.TraitBold)
    }

    var isItalic: Bool
    {
        return fontDescriptor().symbolicTraits.contains(.TraitItalic)
    }

    func setBoldFnc() -> UIFont
    {
        if(isBold)
        {
            return self
        }
        else
        {
            var fontAtrAry = fontDescriptor().symbolicTraits
            fontAtrAry.insert([.TraitBold])
            let fontAtrDetails = fontDescriptor().fontDescriptorWithSymbolicTraits(fontAtrAry)
            return UIFont(descriptor: fontAtrDetails, size: 0)
        }
    }

    func setItalicFnc()-> UIFont
    {
        if(isItalic)
        {
            return self
        }
        else
        {
            var fontAtrAry = fontDescriptor().symbolicTraits
            fontAtrAry.insert([.TraitItalic])
            let fontAtrDetails = fontDescriptor().fontDescriptorWithSymbolicTraits(fontAtrAry)
            return UIFont(descriptor: fontAtrDetails, size: 0)
        }
    }

    func setBoldItalicFnc()-> UIFont
    {
        return setBoldFnc().setItalicFnc()
    }

    func detBoldFnc() -> UIFont
    {
        if(!isBold)
        {
            return self
        }
        else
        {
            var fontAtrAry = fontDescriptor().symbolicTraits
            fontAtrAry.remove([.TraitBold])
            let fontAtrDetails = fontDescriptor().fontDescriptorWithSymbolicTraits(fontAtrAry)
            return UIFont(descriptor: fontAtrDetails, size: 0)
        }
    }

    func detItalicFnc()-> UIFont
    {
        if(!isItalic)
        {
            return self
        }
        else
        {
            var fontAtrAry = fontDescriptor().symbolicTraits
            fontAtrAry.remove([.TraitItalic])
            let fontAtrDetails = fontDescriptor().fontDescriptorWithSymbolicTraits(fontAtrAry)
            return UIFont(descriptor: fontAtrDetails, size: 0)
        }
    }

    func SetNormalFnc()-> UIFont
    {
        return detbBoldFnc().detbItalicFnc()
    }

    func toggleBoldFnc()-> UIFont
    {
        if(isBold)
        {
            return detbBoldFnc()
        }
        else
        {
            return setBoldFnc()
        }
    }

    func toggleItalicFnc()-> UIFont
    {
        if(isItalic)
        {
            return detbItalicFnc()
        }
        else
        {
            return setItalicFnc()
        }
    }
}

5

Swift 3.1

extension UIFont{
var isBold: Bool
{
    return fontDescriptor.symbolicTraits.contains(.traitBold)
}

var isItalic: Bool
{
    return fontDescriptor.symbolicTraits.contains(.traitItalic)
}

func setBold() -> UIFont
{
    if(isBold)
    {
        return self
    }
    else
    {
        var fontAtrAry = fontDescriptor.symbolicTraits
        fontAtrAry.insert([.traitBold])
        let fontAtrDetails = fontDescriptor.withSymbolicTraits(fontAtrAry)
        return UIFont(descriptor: fontAtrDetails!, size: pointSize)
    }
}

func setItalic()-> UIFont
{
    if(isItalic)
    {
        return self
    }
    else
    {
        var fontAtrAry = fontDescriptor.symbolicTraits
        fontAtrAry.insert([.traitItalic])
        let fontAtrDetails = fontDescriptor.withSymbolicTraits(fontAtrAry)
        return UIFont(descriptor: fontAtrDetails!, size: pointSize)
    }
}
func desetBold() -> UIFont
{
    if(!isBold)
    {
        return self
    }
    else
    {
        var fontAtrAry = fontDescriptor.symbolicTraits
        fontAtrAry.remove([.traitBold])
        let fontAtrDetails = fontDescriptor.withSymbolicTraits(fontAtrAry)
        return UIFont(descriptor: fontAtrDetails!, size: pointSize)
    }
}

func desetItalic()-> UIFont
{
    if(!isItalic)
    {
        return self
    }
    else
    {
        var fontAtrAry = fontDescriptor.symbolicTraits
        fontAtrAry.remove([.traitItalic])
        let fontAtrDetails = fontDescriptor.withSymbolicTraits(fontAtrAry)
        return UIFont(descriptor: fontAtrDetails!, size: pointSize)
    }
}
}

3
另一种方法是检查粗体和斜体按钮的选择。
对于粗体:
@IBAction func bold(_ sender : UIButton){
    sender.isSelected = !sender.isSelected
    if sender.isSelected{
        self.textView.font = self.textView.font?.bold()
    }else{
        self.textView.font = self.textView.font?.removeBold()
    }
}

斜体:

@IBAction func italic(_ sender : UIButton){
    sender.isSelected = !sender.isSelected
    if sender.isSelected{
        self.textView.font = self.textView.font?.italic()
    }else{
        self.textView.font = self.textView.font?.removeItalic()
    }
}

UIFont扩展可以包含添加和删除特征的不同方法

在withTraits方法中添加新特征时,请确保保留先前的特征

extension UIFont {

//Add Traits
func withTraits(traits:UIFontDescriptor.SymbolicTraits) -> UIFont {
    let symTraits = fontDescriptor.symbolicTraits
    let descriptor = fontDescriptor.withSymbolicTraits(UIFontDescriptor.SymbolicTraits(arrayLiteral: symTraits, traits))
    return UIFont(descriptor: descriptor!, size: 0) //size 0 means keep the size as it is
}

func bold() -> UIFont {
    return withTraits(traits: .traitBold)
}

func italic() -> UIFont {
    return withTraits(traits: .traitItalic)
}

//remove traits
func withoutTraits(traits:UIFontDescriptor.SymbolicTraits) -> UIFont {
    var symTraits = fontDescriptor.symbolicTraits
    symTraits.remove([traits])
    let fontDescriptorVar = fontDescriptor.withSymbolicTraits(symTraits)
    return UIFont(descriptor: fontDescriptorVar!, size: 0)
}

func removeBold() -> UIFont {
    return withoutTraits(traits: .traitBold)
}

func removeItalic() -> UIFont {
    return withoutTraits(traits: .traitItalic)
}

}

2

SWIFT 3.1

func changeTrait(trait: UIFontDescriptorSymbolicTraits) {
        let range = textView.selectedRange
        let currentAttributes = textView.textStorage.attributes(at: range.location, effectiveRange: nil)
        guard let currentFont = currentAttributes[NSFontAttributeName] as? UIFont else {
            return
        }

        let fontDescriptor = currentFont.fontDescriptor
        var changedFontDescriptor: UIFontDescriptor!


        if fontDescriptor.symbolicTraits.contains(trait) {
            let existingTraitsWithNewTrait = UIFontDescriptorSymbolicTraits(rawValue: fontDescriptor.symbolicTraits.rawValue & ~trait.rawValue)
            changedFontDescriptor = fontDescriptor.withSymbolicTraits(existingTraitsWithNewTrait)
        } else {
            changedFontDescriptor = fontDescriptor.withSymbolicTraits(UIFontDescriptorSymbolicTraits(rawValue: fontDescriptor.symbolicTraits.rawValue | trait.rawValue))
        }

        let updatedFont = UIFont(descriptor: changedFontDescriptor , size: 0)

        let newAttributes = [NSFontAttributeName: updatedFont]
        textView.textStorage.beginEditing()
        textView.textStorage.setAttributes(newAttributes, range: range)
        textView.textStorage.endEditing()
 }

INVOKE:

  1. 粗体: changeTrait(trait: .traitBold)
  2. 斜体: changeTrait(trait: .traitItalic)

0

我不知道我能否帮到你,但我认为你可以这样做:

extension UIFont {

    public static func CreateWithStyle(name: String, size: CGFloat, styles: [UIFontDescriptor.SymbolicTraits]) -> UIFont {

        let fontDescriptor = UIFontDescriptor(name: name, size: size)
        var fontAtrAry = fontDescriptor.symbolicTraits

        if styles.count > 0 {

            for style in styles {
                fontAtrAry.update(with: style)
            }
        }

        return UIFont(descriptor: fontDescriptor.withSymbolicTraits(fontAtrAry)!, size: size)
    }
}

我没有创建删除系统,因为我认为我们不需要它。 当我们创建字体时,我们确定我们想要的样式,就这样。 希望我有所帮助。


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