boundingRectWithSize以及TextKit文字环绕

通过2个例子,复习下textview的相关知识

一.文字计算大小

NSString的这个函数:

- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullable NSDictionary<NSString *, id> *)attributes context:(nullable NSStringDrawingContext *)context NS_AVAILABLE(10_11, 7_0);

用法:

-(void) countBounding{
    NSString * txt = @"大多来问我的朋友们其实都不是很清楚自己的定位,要么是简单的告诉我高考英语考了多少(亲爱的江苏卷的135和全国二卷的135并不是一个层次的好么……),要么简单说一句觉得自己英语很差。只有两个月你给我一句我英语基础不好,怎么才能过四六级,我真的不是神回答不出来的。所以,第一步,也是最最重要的一步,买一本四六级真题(个人买过星火英语的那个黑皮系列卷,不管什么国内的英语考试都可以来一套,很不错,安利一下)。";
    
    
    CGSize size = CGSizeMake(100, 1000);
    // CGSize size = CGSizeMake(1000, 100);
    CGRect rect =  [txt boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:14]} context:nil];
    NSLog(@"rect:s%f, %f",rect.size.width, rect.size.height);
    
    self.textView.text = txt;
    self.textView.frame = CGRectMake( 0, 0, ceil(rect.size.width), ceil(rect.size.height));
}

重要参数:

size:
通常,计算出来的区域是以传入的size的宽度为准则的.在宽度填满的基础上,再计算高度.(文档说的)
所以把我们需要的宽度传入,然后高度写的尽量大,写小了也没关系.

options:

  • NSStringDrawingUsesLineFragmentOrigin 这个必写,文档说的

  • NSStringDrawingUsesFontLeading 计算行高时使用行距。(字体大小+行间距=行距)

  • NSStringDrawingUsesDeviceMetrics 计算时用象形文字的边框而不是印刷字体的边框

  • NSStringDrawingTruncatesLastVisibleLine 如果传入的size装不下所有文本,文本会被省略号结尾.前提是NSStringDrawingUsesLineFragmentOrigin必写,外加String的line break mode必须是NSLineBreakByWordWrapping或者NSLineBreakByCharWrapping

  • attributes 需要的NSAttributeString的特性

附上一张重要的图,说明NSAttributeString的某些属性,来源于官网:

1-1

二. 文字环绕图片

1. 吃点入门概念

如此好的官网不得不看!

TextKit目前和WebKit平级,上面是三个我们熟悉的文本显示控件


2-1
  • NSTextContrainer : 规定了文字要画的矩形(可以是任意形状,NSBezierPath) ,它是UITextView等的属性
  • NSTextStorage : 它是NSMutableAttributedString的子类,它规定了要写的text,以及它们的显示属性
  • NSLayoutManager : 负责把Unicode文字变成象形文字.


    2-2

光看概念和框架只会得到一头雾水.上代码:

-(void ) testAttribute{
    
    NSString * str = @"三个月说一门流利外语没问题,只要你每天不断练习听力、不断模仿着说,尽量学一些贴近生活的句子,毕竟学语言的目的不仅仅是为了考试,更多运用到生活之中。语言学习需要一小时、一小时的积累,不是大家想象中那样几天就可以掌握一门外语。这一点我很赞同,当初自己在学德语时,也是花了一段时间才能够顺利开口说句子。毕竟,你得花时间去学音标、音素,还得花时间去背单词,才会有接下来的开口说.";
    
    
    NSString * str1 = @"培养自制力是一个漫长艰苦的过程。太多的诱惑随时可能让你功亏一篑。所谓的坚持,是心中纠结疑惑,还是继续在往前走,是自己战胜自己的过程。究竟怎样才能排除诸多干扰呢?其实关键就是要学会心理暗示,提前设想那些诱惑带来的种种负面影响,然后在心中一遍又一遍重复告诉自己。";
    
    NSTextStorage * textStorage = [[NSTextStorage alloc] initWithString:str];
    
    
    CGRect rect = CGRectInset(self.view.bounds, 10, 20);
    
    
    //这一段代码很好的诠释了三者的纠结关系,自己体会-----------
    NSLayoutManager * layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];
    NSTextContainer * textContainer = [[NSTextContainer alloc] initWithSize:rect.size];
    [layoutManager addTextContainer:textContainer];
    UITextView * textView = [[UITextView alloc] initWithFrame:rect textContainer:textContainer];
    //-----------
    
    [self.view addSubview:textView];
    
    //官网说这个必须写
    [textStorage beginEditing];

    //1. 通过AttributedString  设置attribute的属性 -- 这里最好写在textStorage初始化的时候,不然就赋值2次string了.是吧.而且实践得知,这样做显示出来非常慢,估计是因为替换了显示的文字的缘故
    
    //这句话给文字赋上了一种风格
    NSDictionary *attrsDic = @{NSTextEffectAttributeName: NSTextEffectLetterpressStyle};
    NSMutableAttributedString * attributeStr = [[NSMutableAttributedString alloc] initWithString:str1 attributes:attrsDic];
    [textStorage setAttributedString:attributeStr];

    
    //2. 通过对textStorage的addAttribute:value:range来后期设置属性
    // 这个让前三个字变红
    [textStorage addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(0, 3)];

    
    [textStorage endEditing];
}

2. 文字环绕

文字环绕其实就是运用了UITextStorage可以设置任意形状这一特性.它有个exclusionPaths属性,是排除文字的区域.官网这图很形象的告诉我们exclusionPaths存在时,文字的具体表现:

2-1

需要注意的是传入的rect必须是相对于textview的rect,而不是图片的frame.
用UIView的函数转换:

- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;

直接上代码:

-(void ) testSurround{
    
    NSString * str = @"三个月说一门流利外语没问题,只要你每天不断练习听力、不断模仿着说,尽量学一些贴近生活的句子,毕竟学语言的目的不仅仅是为了考试,更多运用到生活之中。语言学习需要一小时、一小时的积累,不是大家想象中那样几天就可以掌握一门外语。这一点我很赞同,当初自己在学德语时,也是花了一段时间才能够顺利开口说句子。毕竟,你得花时间去学音标、音素,还得花时间去背单词,才会有接下来的开口说.清朝诗人王永彬曾说:身无饥寒,父母不曾亏我;人无长进,我以何对父母。努力,很多时候不是为了和别人竞争,只是因为我努力就会有收获,没有那么惊天动地,却可以给我带来更丰厚的一笔报酬,给老爸老妈买一件喜欢的衣服,世界那么大,我想带他们去看看。或许努力了依旧过不好自己的一生,改变不了这个社会,但至少,因为努力,我可以成为他们的依靠。或许这就是我们所有普通人努力的意义,为了更有尊严的活着,为了拥有更多选择的机会,为了遇见更好的自己,为了给爱我们的人一点回馈。";
    
    
    UIView* innerView = [[UIView alloc] initWithFrame:CGRectMake(100,100,100, 100)];
    
    [self.view addSubview:innerView];
    
    
    NSTextStorage * textStorage = [[NSTextStorage alloc] initWithString:str];
    
    
    CGRect rect = CGRectInset(self.view.bounds, 10, 20);
    
    
    //这一段代码很好的诠释了三者的纠结关系,自己体会-----------
    NSLayoutManager * layoutManager = [[NSLayoutManager alloc] init];
    [textStorage addLayoutManager:layoutManager];
    NSTextContainer * textContainer = [[NSTextContainer alloc] initWithSize:rect.size];
    [layoutManager addTextContainer:textContainer];

    //-----------
    

    UITextView* textView = [[UITextView alloc] initWithFrame:self.view.bounds textContainer:textContainer];
    
    [self.view insertSubview:textView belowSubview:innerView];
    
    //官网说这个必须写
    [textStorage beginEditing];
    
    //....
    
    [textStorage endEditing];
    
    CGRect relativeRect = [textView convertRect:innerView.frame fromView:self.view];
    UIBezierPath * path =  [UIBezierPath bezierPathWithRect:relativeRect];
    textView.textContainer.exclusionPaths = @[path];
    innerView.backgroundColor = [UIColor redColor];
}

效果:

2-2

Demo

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

推荐阅读更多精彩内容