Swift:UILabel超出寬度文字的截取

JKSwiftExtension,測試用例在 JKContentSizeViewController.swift 里面
需求:單行文字可縮放到一定比例,按照Char截取,超出截掉,不允許出現(xiàn)Char被截取一半的情況

效果圖

一、常規(guī)的剪切方式 (lineBreakMode 設(shè)置文字過長時(shí)的顯示格式)

  • 1.1、NSLineBreakMode枚舉如下

    public enum NSLineBreakMode : Int {
       //  以單詞為顯示單位顯=示,后面部分省略不顯示
       case byWordWrapping = 0 
       // 以字符為顯示單位顯示,后面部分省略不顯示。
       case byCharWrapping = 1 
       // 剪切與文本寬度相同的內(nèi)容長度,后半部分被刪除。
       case byClipping = 2 
       // 前面部分文字以……方式省略,顯示尾部文字內(nèi)容
       case byTruncatingHead = 3 
       // 結(jié)尾部分的內(nèi)容以……方式省略,顯示頭的文字內(nèi)容
       case byTruncatingTail = 4 
       // 中間的內(nèi)容以……方式省略,顯示頭尾的文字內(nèi)容
       case byTruncatingMiddle = 5 
    }
    

    使用如下:以 byWordWrapping 的形式剪切

    let label = UILabel(frame: CGRect(x: 20, y: 20, width: 100, height: 19))
    label.backgroundColor = .yellow
    label.font = UIFont.systemFont(ofSize: 10)
    label.textAlignment = .left
    label.textColor = UIColor.brown
    label.lineBreakMode = .byWordWrapping
    return label
    

二、本次的需求實(shí)現(xiàn)

  • 2.1、需求:單行文字可縮放到一定比例,按照Char截取,超出截掉,不允許出現(xiàn)Char被截取一半的情況

    • 需求分析:可縮放一定比例按照Char截取、不允許出現(xiàn)Char被截取一半的情況
    • 實(shí)現(xiàn)方式:先獲取縮放后的字體大小,后獲取指定寬度的第一行文字的內(nèi)容
  • 2.2、具體的核心代碼如下

    public struct JKContentSize {}
    
    public extension JKContentSize {
        // MARK: 2.1、行數(shù)和每行的內(nèi)容
        /// 獲取已知 width 的 label 的文本行數(shù) & 每一行內(nèi)容
        /// - Parameters:
        ///   - content: 文本的內(nèi)容
        ///   - font: 字體
        ///   - width: 寬度
        ///   - height: 高度
        ///   - minimumScaleFactor: 縮放率
        /// - Returns: 文本行數(shù) & 每一行內(nèi)容
        static func linesCountAndLinesContent(content: String, font: UIFont, width: CGFloat, height: CGFloat, minimumScaleFactor: CGFloat = 1.0) -> (Int?, [String]?) {
            let lodFontName = font.fontName
            let fontSize = getFontSizeForLabel(content: content, minimumScaleFactor: minimumScaleFactor, font: font, width: width, height: height)
            let newFont = UIFont(name: lodFontName, size: fontSize) ?? UIFont.systemFont(ofSize: fontSize)
            let c_fn = newFont.fontName as CFString
            let fp = newFont.pointSize
            let c_f = CTFontCreateWithName(c_fn, fp, nil)
    
            let style = NSMutableParagraphStyle()
            style.lineBreakMode = .byCharWrapping
            let contentDict = [NSAttributedString.Key.paragraphStyle : style] as [NSAttributedString.Key : Any]
            let attr = NSMutableAttributedString(string: content)
            let range = NSRange(location: 0, length: attr.length)
            attr.addAttributes(contentDict, range: range)
            attr.addAttribute(NSAttributedString.Key.font, value: c_f, range: range)
            let frameSetter = CTFramesetterCreateWithAttributedString(attr as CFAttributedString)
      
            let path = CGMutablePath()
            /// 2.5 是經(jīng)驗(yàn)誤差值
            path.addRect(CGRect(x: 0, y: 0, width: width, height: height > (fp * 1.5) ? height : fp * 1.5))
            let framef = CTFramesetterCreateFrame(frameSetter, CFRangeMake(0, 0), path, nil)
            let lines = CTFrameGetLines(framef) as NSArray
            var lineArr = [String]()
            for line in lines {
                let lineRange = CTLineGetStringRange(line as! CTLine)
                let lineString = content.jk.sub(start: lineRange.location, length: lineRange.length)
                lineArr.append(lineString as String)
            }
            return (lineArr.count, lineArr)
        }
    
        // MARK: 獲取字體的大小
        /// 獲取字體的大小
        /// - Returns: 字體的大小
        private static func getFontSizeForLabel(content: String, minimumScaleFactor: CGFloat, font: UIFont, width: CGFloat, height: CGFloat) -> CGFloat {
            let text: NSMutableAttributedString = NSMutableAttributedString(attributedString: NSAttributedString(string: content))
            text.setAttributes([NSAttributedString.Key.font: font as Any], range: NSMakeRange(0, text.length))
            let context: NSStringDrawingContext = NSStringDrawingContext()
            context.minimumScaleFactor = minimumScaleFactor
            text.boundingRect(with: CGSize(width: width, height: height), options: NSStringDrawingOptions.usesLineFragmentOrigin, context: context)
            let adjustedFontSize: CGFloat = font.pointSize * context.actualScaleFactor
            return adjustedFontSize
        }
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容