简体   繁体   中英

Adjust font size of NSMutableAttributedString proportional to UILabel's frame height

In my project, I am using swift 3.0 . Right now I am using following class (UILabel subclass) to adjust font size based on UILabel frame height. When UILabel frame change occurs, layoutSubviews recalculates proportional font size.

class Label: UILabel {

    // FIXME: - properties
    var fontSize: CGFloat = 0
    var frameHeight: CGFloat = 0

    // FIXME: - proportional font size adjustment
    override func layoutSubviews() {
        super.layoutSubviews()
        font = font.withSize(frame.size.height * (fontSize / frameHeight))
    }
}

HOW TO USE:

private let id: Label = {
        let label = Label()
        label.textAlignment = .left
        label.numberOfLines = 1
        label.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
        label.textColor = UIColor(hex: 0x212121, alpha: 1)
        label.fontSize = 17
        label.frameHeight = 20
        label.clipsToBounds = true
        return label
    }()

Now I want to show some part of String in UILabel as BOLD TEXT and remaining in REGULAR TEXT. So I have found some help on this thread: Making text bold using attributed string in swift

I am using "Prajeet Shrestha's" extension for NSMutableAttributedString.

// "Prajeet Shrestha's" extension
extension NSMutableAttributedString {
    func bold(_ text:String) -> NSMutableAttributedString {
        let attrs:[String:AnyObject] = [NSFontAttributeName : UIFont(name: "AvenirNext-Medium", size: 12)!]
        let boldString = NSMutableAttributedString(string:"\(text)", attributes:attrs)
        self.append(boldString)
        return self
    }

    func normal(_ text:String)->NSMutableAttributedString {
        let normal =  NSAttributedString(string: text)
        self.append(normal)
        return self
    }
}

But I am not getting how I can change font size of this NSMutableAttributedString , when UILabel frame change occurs?

Any help appeciated.

Try this

Source Looping Through NSAttributedString Attributes to Increase Font SIze

 mutableStringObj?.enumerateAttribute(NSFontAttributeName, in: NSRange(location: 0, length: mutableStringObj?.length), options: [], usingBlock: {(_ value: Any, _ range: NSRange, _ stop: Bool) -> Void in
            if value {
                var oldFont: UIFont? = (value as? UIFont)
                var newFont: UIFont? = oldFont?.withSize(CGFloat(oldFont?.pointSize * 2))
                res?.removeAttribute(NSFontAttributeName, range: range)
                res?.addAttribute(NSFontAttributeName, value: newFont, range: range)
            }
        })

Try Using label property adjustsFontSizeToFitWidth AND minimumScaleFactor like this:

label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.2

then you also need to increase number of lines like this any number instead of 10

label.numberOfLines = 10

Finally come up with an answer.

I created seperate custom UILabel subclass as follows:

class AttrLabel: UILabel {

    // FIXME: - properties
    var fontSize: CGFloat = 0
    var frameHeight: CGFloat = 0

    // FIXME: - proportional font size adjustment
    override func layoutSubviews() {
        super.layoutSubviews()

        guard let oldAttrText = attributedText else {
            return
        }

        let mutableAttributedText = NSMutableAttributedString(attributedString: oldAttrText)
        mutableAttributedText.beginEditing()

        mutableAttributedText.enumerateAttribute(NSFontAttributeName, in: NSRange(location: 0, length: mutableAttributedText.length), options: []) { (_ value: Any?, _ range: NSRange, _ stop: UnsafeMutablePointer<ObjCBool>) in
            if let attributeFont = value as? UIFont {
                let newFont = attributeFont.withSize(self.frame.size.height * (self.fontSize / self.frameHeight))
                mutableAttributedText.removeAttribute(NSFontAttributeName, range: range)
                mutableAttributedText.addAttribute(NSFontAttributeName, value: newFont, range: range)
            }
        }

        mutableAttributedText.endEditing()
        attributedText = mutableAttributedText
    }
}

HOW TO USE:

private let id: AttrLabel = {
    let label = AttrLabel()
    label.textAlignment = .left
    label.numberOfLines = 1
    label.fontSize = 17
    label.frameHeight = 20
    label.clipsToBounds = true
    return label
}()

SETTING ATTRIBUTED TEXT

let idStr = NSMutableAttributedString()
id.attributedText = idStr.attrStr(text: "BOLD TEXT: ", font: UIFont.systemFont(ofSize: 17, weight: .semibold), textColor: UIColor(hex: 0x212121, alpha: 1)).attrStr(text: "REGULAR WEIGHT TEXT.", font: UIFont.systemFont(ofSize: 17, weight: .regular), textColor: UIColor(hex: 0x212121, alpha: 1))

"Prajeet Shrestha's" extension for NSMutableAttributedString modified by me

extension NSMutableAttributedString {

func attrStr(text: String, font: UIFont, textColor: UIColor) -> NSMutableAttributedString {
        let attributes: [String: Any] = [
                NSFontAttributeName: font,
                NSForegroundColorAttributeName: textColor
        ]
        let string = NSMutableAttributedString(string: text, attributes: attributes)
        self.append(string)
        return self
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM