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 } }