富文本计算最适字体大小

需求就像UILabel上面的sizeToFit(),但是是直接画出来的,没有使用label,
所以自己写了一个计算最适字体大小的方法,保证视图完美容纳富文本

小数在屏幕上会有进位的问题,因此需要保证,计算出的宽度,一定要小于视图的大小,因此ceil了一个px的余量

代码如下:

/// 计算字符串对应的指定宽度的最适字体大小
/// - Parameters:
///   - str: 目标字符串
///   - size: 目标尺寸
///   - baseFont: 基于字体大小开始计算
/// - Returns: 字体的size
func calBestFitFont(str: String, size: CGSize, baseFont: UIFont) -> CGFloat {
    let tmpFont = baseFont.pointSize;

    let attrKeyValues: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.black, .font: baseFont];
    let attr = NSAttributedString(string: str, attributes: attrKeyValues)

    let calSize = attr.boundingRect(with: CGSize(width: CGFloat.greatestFiniteMagnitude, height: tmpFont * 1.5), options: NSStringDrawingOptions.usesLineFragmentOrigin, context: nil).size
    let width = ceil(calSize.width);
    print("中间数据 \(calSize.width)");
    if size.width - width < 1 , size.width - width >= 0{
        return tmpFont
    } else {
        return calBestFitFont(str: str, size: size, baseFont: UIFont.systemFont(ofSize: tmpFont * (size.width/width)))
    }
}

实际测试效果如下,基本保证使用3次计算即可达到合适大小,比一个字号一个字号的循环要好多了。

至于这里的width,为什么要ceil, 一个是误差在1px以内的时候,可以认为达到目标,二是因为,当数据算到小数点后好多位的时候,字体的size的比值已经很相近,导致无限循环,就像一碗水,每次取一半,那永远也取不完

中间数据 164.91975778341293
中间数据 55.42169744318181
中间数据 49.48365843141235
string:4s7gxSwcAUuVgKW-------------fontSize:4.870129870129871
中间数据 80.72781318426132
中间数据 52.64756944444444
中间数据 49.995086477987414
string:n4TGo9Yl-------------fontSize:10.482180293501049
中间数据 49.71966540813446
string:dQMg-------------fontSize:18.0
中间数据 318.7265405058861
中间数据 55.411044034090914
中间数据 49.47414645900973
string:fvQEnAmKW41HgMG2uesccwLVUfBQv-------------fontSize:2.5190326914464847
中间数据 204.88192015886307
中间数据 56.4064881859756
中间数据 49.47937560173298
string:bYo9F8tGlcTLqCTGijB0gf-------------fontSize:3.851091142490372
中间数据 29.534398913383484
中间数据 48.10546875
中间数据 49.04237085459184
string:JKx-------------fontSize:30.612244897959183
中间数据 234.21144711971283
中间数据 55.18409242021278
中间数据 49.271511089475695
string:QZQEwYU69wNpTdodLwBxq-------------fontSize:3.4194528875379944
中间数据 126.98018860816956
中间数据 55.01468688484253
中间数据 49.528072601764634
string:W0z5NP3BkTxr-------------fontSize:6.327334083239596
中间数据 272.7897495031357
中间数据 55.88781335851647
中间数据 49.899833355818295
string:ZwoR9ktNza1oO6oRl3b0cV2Rf3n-------------fontSize:2.9434850863422293
中间数据 11.6578808426857
中间数据 47.71728515625
中间数据 49.62921142578125
string:A-------------fontSize:78.125
中间数据 189.93099957704544
中间数据 55.345651726973685
中间数据 49.41576047051221
string:WyjCmRa1RsuWaEmCZ-------------fontSize:4.2293233082706765
中间数据 216.786294400692
中间数据 55.77004428283411
中间数据 49.794682395387596
string:h4KwwTiPtxO3O2evWx4rc-------------fontSize:3.70309414088216
中间数据 281.1776897907257
中间数据 55.80743018617021
中间数据 49.82806266622339
string:xjT6alXodf2wXfAMQlOm3jsd4AUD-------------fontSize:2.8495440729483286
中间数据 274.6182419657707
中间数据 55.61878551136364
中间数据 49.659629920860404
string:G4YEqUTLdaKIvfboUhxO3HmTgX-------------fontSize:2.9220779220779223
中间数据 67.288991689682
中间数据 51.015337775735304
中间数据 49.27691291360295
string:GgJ95G-------------fontSize:12.726244343891404
中间数据 40.56106263399124
中间数据 48.44740360248379
中间数据 49.40017397692098
string:z5xX-------------fontSize:22.399203583872573
中间数据 69.38357323408127
中间数据 51.22767857142857
中间数据 49.47469522664835
string:v3DVND-------------fontSize:12.362637362637363
中间数据 207.29972451925278
中间数据 55.32883864182692
中间数据 49.400748787345464
string:oMpoVkHYuvtSwu4QSDo-------------fontSize:3.8633241758241756
中间数据 226.44070726633072
中间数据 55.678904529185026
中间数据 49.713307615343766
string:9OGFOojCGNoFAEy0rCclgv-------------fontSize:3.539962240402769
中间数据 63.36066430807114
中间数据 50.8392333984375
中间数据 49.96355842141544
string:CBv2k5-------------fontSize:13.786764705882351
中间数据 233.3273132443428
中间数据 55.74669471153845
中间数据 49.77383456387362
string:Cbqp9lFCfaca4aHgOVBulU9-------------fontSize:3.434065934065934
中间数据 92.57904696464539
中间数据 53.66998487903225
中间数据 50.13195844534049
中间数据 49.277663574390324
string:XPhbp62lvi-------------fontSize:8.784875957551478
中间数据 234.39156979322433
中间数据 55.74696642287235
中间数据 49.774077163278875
string:bAEnzVpXlAB87xqHqkyhtoW-------------fontSize:3.4194528875379944
中间数据 280.830139875412
中间数据 55.9356580849644
中间数据 49.942551861575375
string:q5hAtiX0luvOMabIAN0UFnbyN81d-------------fontSize:2.859684799186579

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容