swift4.0: 獲取字符高度 (UILabel+GetSize && String+GetSize)

//
//  Label+Getheight.swift
//  LabelH
//
//  Created by 李鵬躍 on 2018/6/25.
//  Copyright ? 2018年 李鵬躍. All rights reserved.
//

import UIKit

extension UILabel {
    enum GetSizeType_ENUM: Int {
        case text = 0
        case attributeString
    }
    
    ///  自動計算了label 的寬度,在此之前,需要有l(wèi)abel的寬度約束
    ///
    /// - Returns:
    
    
    /// 獲取label的高度,
    ///
    /// - Parameters:
    ///   - type: 計算text 還是attributeText,如果不傳則(如果有text的話,優(yōu)先計算attributeText的height,沒有attributeText則計算text的height,如果兩個都沒有值則返回0)
    ///   - width: width的最大值。如果不傳則(自動計算了label 的width,在此之前,需要有l(wèi)abel的width約束)
    /// - Returns: 文本實際高度的最大值
    func getLabelHeight(type: GetSizeType_ENUM? = nil, width: CGFloat? = nil) -> CGFloat {
        var w: CGFloat = width ?? -1
        var h: CGFloat = CGFloat.greatestFiniteMagnitude
        if w <= 0 {
            if frame.width == 0 {
                layoutIfNeeded()
            }
            guard frame.width != 0 else {
                print("??????: 計算label的height失敗,因為其width為0")
                return 0
            }
            w = frame.width
        }
        
        if let attributedText = attributedText, let type = type, type == .attributeString{
            
            h = attributedText.getSize(width: w, height: h).height
        }else if let text = text {
            
            h = text.getLableHeigh(font: font, width: w)
        }else {
            print("label沒有text,或者attribute")
        }
        return h
    }
    
    
    /// 獲取label的widht,
    ///
    /// - Parameters:
    ///   - type: 計算text 還是attributeText,如果不傳則(如果有text的話,優(yōu)先計算attributeText的width,沒有attributeText則計算text的width,如果兩個都沒有值則返回0)
    ///   - height: 高度的最大值。如果不傳則(自動計算了label 的height,在此之前,需要有l(wèi)abel的height約束)
    /// - Returns: 文本的寬度最大值
    func getLabelWidth(type: GetSizeType_ENUM? = nil, height: CGFloat? = nil) -> CGFloat {
        
        var w: CGFloat = CGFloat.greatestFiniteMagnitude
        var h: CGFloat = height ?? -1
        if h <= 0 {
            if frame.width == 0 {
                layoutIfNeeded()
            }
            guard frame.height != 0 else {
                print("??????: 計算label的width失敗,因為其height為0")
                return 0
            }
            h = frame.height
        }
        
        if let attributedText = attributedText, let type = type, type == .attributeString{
            
            w = attributedText.getSize(width: w, height: h).width
        }else if let text = text {
            
            w = text.getLableWidth(font: font, height: h)
        }else {
            print("label沒有text,或者attribute")
        }
        return w + 1
    }
    
    
    /// 限制最大漢字?jǐn)?shù)
    ///
    /// - Parameters:
    ///   - maxCount: 最多顯示多少個字
    /// - Returns: label的寬度
    func getLabelWidth(type: GetSizeType_ENUM? = nil, height: CGFloat? = nil, maxCount: Int64) -> CGFloat {
        
        var str = "哈"
        for _ in 0 ..< maxCount {
            str += "哈"
        }
        
        let text = self.text
        let attributedText = self.attributedText
        let textW = getLabelWidth(type: type, height: height)
        
        self.text = str
        let strW = getLabelWidth(height: height)
        
        self.text = text
        self.attributedText = attributedText
        return strW < textW ? strW : textW
    }

}



// MARK: - get NSAttributedString height
extension NSAttributedString {
    
    /// 根據(jù)給定的范圍計算寬高,如果計算寬度,則請把寬度設(shè)置為最大,計算高度則設(shè)置高度為最大
    ///
    /// - Parameters:
    ///   - width: 寬度的最大值
    ///   - height: 高度的最大值
    /// - Returns: 文本的實際size
    func getSize(width: CGFloat,height: CGFloat) -> CGSize {
        let attributed = self
        let ctFramesetter = CTFramesetterCreateWithAttributedString(attributed)
        let rect = CGRect.init(x: 0, y: 0, width: width, height: height)
        let framesetter = CTFramesetterCreateWithAttributedString(attributed)
        let size = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRange.init(location: 0, length: attributed.length), nil, rect.size, nil)
        return CGSize.init(width: size.width + 1, height: size.height + 1)
    }
    
    func getImageRunFrame(run: CTRun, lineOringinPoint: CGPoint, offsetX: CGFloat) -> CGRect {
        /// 計算位置 大小
        var runBounds = CGRect.zero
        var h: CGFloat = 0
        var w: CGFloat = 0
        var x: CGFloat = 0
        var y: CGFloat = 0
        
        var asecnt: CGFloat = 0
        var descent: CGFloat = 0
        var leading: CGFloat = 0
        
        
        let cfRange = CFRange.init(location: 0, length: 0)
        
        w = CGFloat(CTRunGetTypographicBounds(run, cfRange, &asecnt, &descent, &leading))
        h = asecnt + descent + leading
        /// 獲取具體的文字距離這行原點的距離 || 算尺寸用的
        x = offsetX + lineOringinPoint.x
        /// y
        y = lineOringinPoint.y - descent
        runBounds = CGRect.init(x: x, y: y, width: w, height: h)
        return runBounds
    }
}


// MARK: - get String height
extension String {
    func getLableHeigh(font:UIFont,width:CGFloat) -> CGFloat {
        
        let size = CGSize.init(width: width, height:  CGFloat(MAXFLOAT))
        
        //        let dic = [NSAttributedStringKey.font:font] // swift 4.0
        let dic = [NSAttributedStringKey.font:font] // swift 3.0
        
        let strSize = self.boundingRect(with: size, options: [.usesLineFragmentOrigin], attributes: dic, context:nil).size
        
        return ceil(strSize.height) + 1
    }
    ///獲取字符串的寬度
    func getLableWidth(font:UIFont,height:CGFloat) -> CGFloat {
        
        let size = CGSize.init(width: CGFloat(MAXFLOAT), height: height)
        
        //        let dic = [NSAttributedStringKey.font:font] // swift 4.0
        let dic = [NSAttributedStringKey.font:font] // swift 3.0
        
        let cString = self.cString(using: String.Encoding.utf8)
        let str = String.init(cString: cString!, encoding: String.Encoding.utf8)
        let strSize = str?.boundingRect(with: size, options: .usesLineFragmentOrigin, attributes: dic, context:nil).size
        return strSize?.width ?? 0
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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