ios 在 Swift 中将 UILabel 的一部分设为粗体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36486761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 08:53:11  来源:igfitidea点击:

Make part of a UILabel bold in Swift

iosstringswiftuilabelnsrange

提问by Nick89

I have a UILabelI've made programmatically as:

我有一个UILabel我以编程方式制作的:

var label = UILabel()

I've then declared some styling for the label, including a font, such as:

然后,我为标签声明了一些样式,包括字体,例如:

label.frame = CGRect(x: 20, y: myHeaderView.frame.height / 2, width: 300, height: 30)
label.font = UIFont(name: "Typo GeoSlab Regular Demo", size: 15)
label.textColor = UIColor(hue: 0/360, saturation: 0/100, brightness: 91/100, alpha: 1)

The first part of the label will always read : "Filter:"then followed by another part of the string, for example, "Most popular"

标签的第一部分将始终为:"Filter:"然后是字符串的另一部分,例如,“最流行”

I would like the word filter to be in bold, so the whole thing would look like:

我希望过滤器这个词是粗体的,所以整个事情看起来像:

Filter:Most popular

过滤器:最受欢迎

I want to simplest way of creating this effect. I've been searching the internet for how to achieve this and there are so many ways, some which just look like pages of code. And most of it seems to be in Objective-C. I would like it in Swift please :)

我想用最简单的方法来创造这种效果。我一直在互联网上搜索如何实现这一点,有很多方法,有些看起来就像代码页。而且大部分似乎都在Objective-C中。我想在 Swift 中使用它 :)

I don't know if i'm on the right lines, but is this what NSRangecan help achieve? Thanks in advance

我不知道我是否在正确的路线上,但这是NSRange可以帮助实现的吗?提前致谢

Update

更新

I use a series of ifstatements to change my labelvariable. Such as:

我使用一系列if语句来更改我的label变量。如:

if indexArray == 1 {

    label.text = "Filter: Film name"

} else if indexArray == 2 {

    label.text = "Filter: Most popular"

} else if indexArray == 3 {

    label.text = "Filter: Star rating"

}

回答by Joe Benton

You will want to use attributedStringwhich allows you to style parts of a string etc. This can be done like this by having two styles, one normal, one bold, and then attaching them together:

您将需要使用attributedStringwhich 允许您为字符串的某些部分设置样式等。 这可以通过使用两种样式来完成,一种是普通样式,一种是粗体,然后将它们连接在一起:

let boldText = "Filter:"
let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 15)]
let attributedString = NSMutableAttributedString(string:boldText, attributes:attrs)

let normalText = "Hi am normal"
let normalString = NSMutableAttributedString(string:normalText)

attributedString.append(normalString)

When you want to assign it to a label:

当您想将其分配给标签时:

label.attributedText = attributedString

回答by abdullahselek

You can use NSMutableAttributedString and NSAttributedString to create customized string. The function below makes given boldString bold in given string.

您可以使用 NSMutableAttributedString 和 NSAttributedString 来创建自定义字符串。下面的函数使给定的 boldString 在给定的字符串中加粗。

Swift 3

斯威夫特 3

func attributedText(withString string: String, boldString: String, font: UIFont) -> NSAttributedString {
    let attributedString = NSMutableAttributedString(string: string,
                                                     attributes: [NSFontAttributeName: font])
    let boldFontAttribute: [String: Any] = [NSFontAttributeName: UIFont.boldSystemFont(ofSize: font.pointSize)]
    let range = (string as NSString).range(of: boldString)
    attributedString.addAttributes(boldFontAttribute, range: range)
    return attributedString
}

Example usage

示例用法

authorLabel.attributedText = attributedText(withString: String(format: "Author : %@", user.name), boldString: "Author", font: authorLabel.font)

Swift 4

斯威夫特 4

func attributedText(withString string: String, boldString: String, font: UIFont) -> NSAttributedString {
    let attributedString = NSMutableAttributedString(string: string,
                                                     attributes: [NSAttributedStringKey.font: font])
    let boldFontAttribute: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: font.pointSize)]
    let range = (string as NSString).range(of: boldString)
    attributedString.addAttributes(boldFontAttribute, range: range)
    return attributedString
}

Swift 4.2 and 5

斯威夫特 4.2 和 5

func attributedText(withString string: String, boldString: String, font: UIFont) -> NSAttributedString {
    let attributedString = NSMutableAttributedString(string: string,
                                                 attributes: [NSAttributedString.Key.font: font])
    let boldFontAttribute: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: font.pointSize)]
    let range = (string as NSString).range(of: boldString)
    attributedString.addAttributes(boldFontAttribute, range: range)
    return attributedString
}

回答by Lloyd Keijzer

Result:

结果:

enter image description here

在此处输入图片说明

Swift 4.2 & 5.0:

斯威夫特 4.2 和 5.0:

First off we create a protocol that both UILabeland UITextFieldcan adopt.

首先,我们创建了一个既可以采用UILabelUITextField可以采用的协议。

public protocol ChangableFont: AnyObject {
    var text: String? { get set }
    var attributedText: NSAttributedString? { get set }
    var rangedAttributes: [RangedAttributes] { get }
    func getFont() -> UIFont?
    func changeFont(ofText text: String, with font: UIFont)
    func changeFont(inRange range: NSRange, with font: UIFont)
    func changeTextColor(ofText text: String, with color: UIColor)
    func changeTextColor(inRange range: NSRange, with color: UIColor)
    func resetFontChanges()
}

We want to be able to add multiple changes to our text, therefore we create the rangedAttributesproperty. It's a custom struct that holds attributes and the range in which they are applied.

我们希望能够为我们的文本添加多个更改,因此我们创建了该rangedAttributes属性。它是一个自定义结构,包含属性和应用它们的范围。

public struct RangedAttributes {

    let attributes: [NSAttributedString.Key: Any]
    let range: NSRange

    public init(_ attributes: [NSAttributedString.Key: Any], inRange range: NSRange) {
        self.attributes = attributes
        self.range = range
    }
}

Another problem is that UILabelits fontproperty is strong and UITextFieldits fontproperty is weak/optional. To make them both work with our ChangableFontprotocol we include the getFont() -> UIFont?method.

另一个问题是UILabel它的font属性是强的,而UITextField它的font属性是弱/可选的。为了使它们都适用于我们的ChangableFont协议,我们包含了该getFont() -> UIFont?方法。

extension UILabel: ChangableFont {

    public func getFont() -> UIFont? {
        return font
    }
}

extension UITextField: ChangableFont {

    public func getFont() -> UIFont? {
        return font
    }
}

Now we can go ahead and create the default implementation for both UILabeland UITextFieldby extending our protocol.

现在我们可以继续为两者创建默认实现,UILabelUITextField通过扩展我们的协议。

public extension ChangableFont {

    public var rangedAttributes: [RangedAttributes] {
        guard let attributedText = attributedText else {
            return []
        }
        var rangedAttributes: [RangedAttributes] = []
        let fullRange = NSRange(
            location: 0,
            length: attributedText.string.count
        )
        attributedText.enumerateAttributes(
            in: fullRange,
            options: []
        ) { (attributes, range, stop) in
            guard range != fullRange, !attributes.isEmpty else { return }
            rangedAttributes.append(RangedAttributes(attributes, inRange: range))
        }
        return rangedAttributes
    }

    public func changeFont(ofText text: String, with font: UIFont) {
        guard let range = (self.attributedText?.string ?? self.text)?.range(ofText: text) else { return }
        changeFont(inRange: range, with: font)
    }

    public func changeFont(inRange range: NSRange, with font: UIFont) {
        add(attributes: [.font: font], inRange: range)
    }

    public func changeTextColor(ofText text: String, with color: UIColor) {
        guard let range = (self.attributedText?.string ?? self.text)?.range(ofText: text) else { return }
        changeTextColor(inRange: range, with: color)
    }

    public func changeTextColor(inRange range: NSRange, with color: UIColor) {
        add(attributes: [.foregroundColor: color], inRange: range)
    }

    private func add(attributes: [NSAttributedString.Key: Any], inRange range: NSRange) {
        guard !attributes.isEmpty else { return }

        var rangedAttributes: [RangedAttributes] = self.rangedAttributes

        var attributedString: NSMutableAttributedString

        if let attributedText = attributedText {
            attributedString = NSMutableAttributedString(attributedString: attributedText)
        } else if let text = text {
            attributedString = NSMutableAttributedString(string: text)
        } else {
            return
        }

        rangedAttributes.append(RangedAttributes(attributes, inRange: range))

        rangedAttributes.forEach { (rangedAttributes) in
            attributedString.addAttributes(
                rangedAttributes.attributes,
                range: rangedAttributes.range
            )
        }

        attributedText = attributedString
    }

    public func resetFontChanges() {
        guard let text = text else { return }
        attributedText = NSMutableAttributedString(string: text)
    }
}

With in the default implementation I use a little helper method for getting the NSRangeof a substring.

在默认实现我用得到一个小帮手方法NSRangesubstring

public extension String {

    public func range(ofText text: String) -> NSRange {
        let fullText = self
        let range = (fullText as NSString).range(of: text)
        return range
    }
}

We're done!You can now change parts of the text its font and text color.

我们完成了!您现在可以更改部分文本的字体和文本颜色。

titleLabel.text = "Welcome"
titleLabel.font = UIFont.systemFont(ofSize: 70, weight: .bold)
titleLabel.textColor = UIColor.black
titleLabel.changeFont(ofText: "lc", with: UIFont.systemFont(ofSize: 60, weight: .light))
titleLabel.changeTextColor(ofText: "el", with: UIColor.blue)
titleLabel.changeTextColor(ofText: "co", with: UIColor.red)
titleLabel.changeTextColor(ofText: "m", with: UIColor.green)

回答by Maksim Kniazev

Swift 4 alternative:

Swift 4 替代方案

let attrs = [NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 14)]
let attributedString = NSMutableAttributedString(string: "BOLD TEXT", attributes:attrs)
let normalString = NSMutableAttributedString(string: "normal text")
attributedString.append(normalString)
myLabel.attributedText = attributedString

回答by Glenn

Just sharing my own quite-flexible implementation in Swift 4.0. Cause there are some requirements, like mine currently, that you need to set not only bold but italic the part of a label's text.

只是在 Swift 4.0 中分享我自己的非常灵活的实现。因为有一些要求,例如我目前的要求,您不仅需要将标签文本的部分设置为粗体,还需要设置为斜体。

import UIKit

extension UILabel {

    /** Sets up the label with two different kinds of attributes in its attributed text.
     *  @params:
     *  - primaryString: the normal attributed string.
     *  - secondaryString: the bold or highlighted string.
     */

    func setAttributedText(primaryString: String, textColor: UIColor, font: UIFont, secondaryString: String, secondaryTextColor: UIColor, secondaryFont: UIFont) {

        let completeString = "\(primaryString) \(secondaryString)"

        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.alignment = .center

        let completeAttributedString = NSMutableAttributedString(
            string: completeString, attributes: [
                .font: font,
                .foregroundColor: textColor,
                .paragraphStyle: paragraphStyle
            ]
        )

        let secondStringAttribute: [NSAttributedStringKey: Any] = [
            .font: secondaryFont,
            .foregroundColor: secondaryTextColor,
            .paragraphStyle: paragraphStyle
        ]

        let range = (completeString as NSString).range(of: secondaryString)

        completeAttributedString.addAttributes(secondStringAttribute, range: range)

        self.attributedText = completeAttributedString
    }
}

回答by Stefano Pedroli

You can directly do on String if you prefer:

如果你愿意,你可以直接在 String 上做:

extension String {
func withBoldText(text: String, font: UIFont? = nil) -> NSAttributedString {
  let _font = font ?? UIFont.systemFont(ofSize: 14, weight: .regular)
  let fullString = NSMutableAttributedString(string: self, attributes: [NSAttributedString.Key.font: _font])
  let boldFontAttribute: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: _font.pointSize)]
  let range = (self as NSString).range(of: text)
  fullString.addAttributes(boldFontAttribute, range: range)
  return fullString
}}

Usage:

用法:

label.attributeString = "my full string".withBoldText(text: "full")

回答by Oz Shabat

for the ones who prefer extensions

对于喜欢扩展的人

Swift 5.0

斯威夫特 5.0

    /// will set a regual and a bold text in the same label
    public func setRegualAndBoldText(regualText: String,
                                       boldiText: String) {

        let attrs = [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: font.pointSize)]
        let regularString = NSMutableAttributedString(string: regualText)
        let boldiString = NSMutableAttributedString(string: boldiText, attributes:attrs)
        regularString.append(boldiString)
        attributedText = regularString
    }

and use:

并使用:

label.setRegualAndBoldText(regualText: "height: ", boldiText: "1.65 :(")

回答by apinho

Swift 4.0 solution

Swift 4.0 解决方案

let font = UIFont.systemFont(ofSize: 14)

func boldSearchResult(searchString: String, resultString: String) -> NSMutableAttributedString {
    let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: resultString)

    guard let regex  = try? NSRegularExpression(pattern: searchString.lowercased(), options: []) else {
        return attributedString
    }

    let range: NSRange = NSMakeRange(0, resultString.count)

    regex.enumerateMatches(in: resultString.lowercased(), options: [], range: range) { (textCheckingResult, matchingFlags, stop) in
        guard let subRange = textCheckingResult?.range else {
            return
        }

        attributedString.addAttributes([NSAttributedString.Key.font : font], range: subRange)
    }

    return attributedString
}