解决NSTextContainer分页时文本截断问题

NSTextContainer与NSLayoutManager配合使用可以将大文本文件分页,但是,分页过程中会遇到问题,显示字符被截断的问题:)

- (void)viewDidLoad
{[super viewDidLoad];// 数据源NSString *string = [NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"bubizhidaowoshishui" withExtension:@"txt"] usedEncoding:nilerror:nil];// 文本容器NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string];// 文本容器的布局管理器NSLayoutManager *layoutManager = [NSLayoutManager new];[storage addLayoutManager:layoutManager];// 分段显示文本容器中的内容CGSize size = CGSizeMake(300, 540);NSTextContainer *textContainer1 = [[NSTextContainer alloc] initWithSize:size];[layoutManager addTextContainer:textContainer1];NSTextContainer *textContainer2 = [[NSTextContainer alloc] initWithSize:size];[layoutManager addTextContainer:textContainer2];NSTextContainer *textContainer3 = [[NSTextContainer alloc] initWithSize:size];[layoutManager addTextContainer:textContainer3];UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 20,size.width,size.height)textContainer:textContainer3];textView.layer.borderWidth = 1;textView.scrollEnabled     = NO;textView.editable          = NO;[self.view addSubview:textView];
}

以下是我的运行结果(注意看底下红色的部分,文本被截断了哦):

为什么会被截断呢,按理说,NSLayoutManager会计算好一个size值然后给NSTextContainer让这个NSTextContainer自己适应的.

苹果官方文档里面有描述:

Generating Line Fragment Rectangles

The layout manager lays text within an NSTextContainer object in lines of glyphs. The layout of these lines within the text container is determined by its shape and by any exclusion paths it contains. Wherever the line fragment rectangle intersects a region defined by an exclusion path, the lines in those parts must be shortened or fragmented; if there’s a gap across the entire region, the lines that would overlap it have to be shifted to compensate.

The layout manager proposes a rectangle for a given line and then asks the text container to adjust the rectangle to fit. The proposed rectangle usually spans the text container’s bounding rectangle, but it can be narrower or wider, and it can also lie partially or completely outside the bounding rectangle. The message that the layout manager sends the text container to adjust the proposed rectangle islineFragmentRectForProposedRect:atIndex:writingDirection:remainingRect:, which returns the largest rectangle available for the proposed rectangle, based on the direction in which text is laid out. It also returns a rectangle containing any remaining space, such as the space left on the other side of a hole or gap in the text container.

The layout manager makes one final adjustment when it actually fits text into the rectangle. This adjustment is a small amount fixed by the text container, called the line fragment padding, which defines the portion on each end of the line fragment rectangle left blank. Text is inset within the line fragment rectangle by this amount (the rectangle itself is unaffected). Padding allows for small-scale adjustment of the text container’s region at the edges (and around any holes) and keeps text from directly abutting any other graphics displayed near the region. You can change the padding from its default value with the lineFragmentPadding property. Note that line fragment padding isn’t a suitable means for expressing margins. For document margins, you should set theUITextView object’s position and size within its enclosing view. And for text margins, you should set thetextContainerInset property of the text view. In addition, you can set indentation values for individual paragraphs using NSMutableParagraphStyle properties such as headIndent.

In addition to returning the line fragment rectangle itself, the layout manager returns a rectangle called the used rectangle. This is the portion of the line fragment rectangle that actually contains glyphs or other marks to be drawn. By convention, both rectangles include the line fragment padding and the interline space (which is calculated from the font’s line height metrics and the paragraph’s line spacing parameters). However, the paragraph spacing (before and after) and any space added around the text, such as that caused by center-spaced text, are included only in the line fragment rectangle, and are not included in the used rectangle.

每个NSTextContainer的frame值都是被NSLayoutManager粗略计算过的,与你设置NSTextContainer的size值略有出入,有时候大些,有时候小些,但误差绝度不会超过一个字符的高度.所以,苹果建议我们在设置UITextView的时候,给这个NSTextContainer预留一定的高度......

解决的方法如下:

效果如下:

这个问题有这么棘手么?其实,我是在黔驴技穷的情况下(github上下载了7-8个相关demo,stackoverflow上搜寻等等途径都无效的情况下)细致研究官方提供的pdf文档才明白过来的:),你懂的.

附录:

使用自定义字体不是梦:)

- (void)viewDidLoad
{[super viewDidLoad];// 数据源NSString *string = [NSString stringWithContentsOfURL:[NSBundle.mainBundle URLForResource:@"bubizhidaowoshishui" withExtension:@"txt"] usedEncoding:nilerror:nil];// 文本容器NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string];// 文本容器的布局管理器NSLayoutManager *layoutManager = [NSLayoutManager new];[storage addLayoutManager:layoutManager];// 段落属性NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];paragraphStyle.lineHeightMultiple  = 1.f;                    // 可变行高,乘因数paragraphStyle.lineSpacing         = 5.f;                    // 行间距paragraphStyle.minimumLineHeight   = 10.f;                   // 最小行高paragraphStyle.maximumLineHeight   = 20.f;                   // 最大行高paragraphStyle.paragraphSpacing    = 10.f;                   // 段间距paragraphStyle.alignment           = NSTextAlignmentLeft;    // 对齐方式paragraphStyle.firstLineHeadIndent = 30.f;                   // 段落首文字离边缘间距paragraphStyle.headIndent          = 0.f;                    // 段落除了第一行的其他文字离边缘间距paragraphStyle.tailIndent          = 0.f;                    // ???????[storage addAttribute:NSParagraphStyleAttributeNamevalue:paragraphStylerange:NSMakeRange(0, storage.string.length)];// 字体属性[storage addAttribute:NSFontAttributeNamevalue:[UIFont fontWithName:CUSTOM_FONT(@"新蒂小丸子体", 0) size:15.f]range:NSMakeRange(0, storage.string.length)];[storage addAttribute:NSForegroundColorAttributeNamevalue:[UIColor redColor]range:NSMakeRange(0, storage.string.length)];// 分段显示文本容器中的内容CGSize size = CGSizeMake(300, 520);NSTextContainer *textContainer1 = [[NSTextContainer alloc] initWithSize:size];[layoutManager addTextContainer:textContainer1];NSTextContainer *textContainer2 = [[NSTextContainer alloc] initWithSize:size];[layoutManager addTextContainer:textContainer2];NSTextContainer *textContainer3 = [[NSTextContainer alloc] initWithSize:size];[layoutManager addTextContainer:textContainer3];UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 20,size.width,size.height + 20)textContainer:textContainer3];textView.layer.borderWidth = 1;textView.scrollEnabled     = NO;textView.editable          = NO;[self.view addSubview:textView];
}

解决NSTextContainer分页时文本截断问题相关推荐

  1. excel导入mysql 截断_解决Excel导入数据库时出现的文本截断问题

    问题 在把Excel导入到数据库中时,发生文本截断问题:即导入的数据每行只有一部分,原始的Excel数据为: 忽略错误 导入SQLServer2008过程中,如果源数据和目标数据类型不匹配会导入失败, ...

  2. excel数据导入mysql被截取_Excel导入数据库时出现的文本截断问题解决方案

    问题 在把Excel导入到数据库中时,发生文本截断问题:即导入的数据每行只有一部分,原始的Excel数据为: 忽略错误 导入SQLServer2008过程中,如果源数据和目标数据类型不匹配会导入失败, ...

  3. excel导入mysql 截断_Excel导入数据库时出现的文本截断问题解决方案

    问题 在把Excel导入到数据库中时,发生文本截断问题:即导入的数据每行只有一部分,原始的Excel数据为: 忽略错误 导入SQLServer2008过程中,如果源数据和目标数据类型不匹配会导入失败, ...

  4. 解决 Elasticsearch 分页查询记录超过10000时异常

    问题一: 查询结果中 hits.total.value 值最大为10000的限制 解决方法: 请求时设置 "track_total_hits": true Rest 请求设置方法: ...

  5. mysql 当前记录集不支持书签_关于使用视图进行分页时出现当前记录集不支持书签的错误解决方法及原因(asp)...

    一般在使用视图进行查询时,视图中意般都关联了两个或者更多个表,一般在这种情况下才会使用视图,但是但我在使用视图来查询数据时没有问题,但是一旦在分页中使用到视图进行查询就会出现错误提示如下: ADODB ...

  6. 关于Static控件背景透明时文本覆盖重影的问题

    2019独角兽企业重金招聘Python工程师标准>>> 关于Static控件背景透明时文本覆盖重影的问题 通过映射OnCtlColor消息,而后在该函数中使用pDC->SetB ...

  7. 全局异步和主线程异步区别、改变PlaceHolder颜色、解决键盘弹起挡住文本框问题...

    1.全局异步执行耗时任务 dispatch_async(dispatch_get_global_queue(0, 0), ^{ }); 2.主线程异步刷新UI dispatch_async(dispa ...

  8. 用JS解决多行溢出文本的省略问题

    前言 在项目开发过程中,经常会遇到溢出文本的省略问题.根据需求,可以把文本省略分为单行文本省略和多行文本省略两类. 单行文本的省略,现在css样式 text-overflow 已经有兼容性很好的样式支 ...

  9. ElasticSearch利用Search After解决深度分页问题

    ElasticSearch利用Search After解决深度分页问题 1.ElasticSearch常见分页 2.ElasticSearch深度分页问题 3.ElasticSearch深度分页问题的 ...

最新文章

  1. 父窗口控制弹出窗口快捷键ctrl+c关闭
  2. 联机重做日志的配置过程
  3. 查看Windows端口及端口关闭方法
  4. SVM支持向量机--sklearn研究
  5. Swift 开发的工具类,主要是提供正则表达式及其它,Github会长期维护
  6. Localdatetime
  7. 【渝粤教育】电大中专建筑力学作业 题库
  8. Spring Boot:(二)启动原理解析
  9. 从Client应用场景介绍IdentityServer4(二)
  10. 使用ADD命令将目录复制到Docker的其他目录
  11. 轻松搭建Windows8云平台开发环境
  12. 几行代码就能实现为何要多此一举
  13. 在Android浏览器下字体偏上的问题
  14. fcntl实现对文件加锁功能
  15. 【红昭愿】MMD动作镜头下载
  16. Avalondock 第一步 创建停靠面板
  17. 几种常用的电机控制法
  18. 工业摄像头传感器尺寸与像元尺寸的关系
  19. 区块链教程之Bitcoin公钥和地址生成
  20. CI和Smarty整合并且前后台加载不同配置文件使前台应用Smarty缓存后台不应用

热门文章

  1. 使用 ReSharper对.NET解决方案进行全面重构
  2. PHP导出CSV文件出现乱码的解决方法
  3. IDEA控制台乱码终极解决方案
  4. 解决使用elementUI框架el-upload跨域上传时session丢失问题
  5. 问题解决: 此文件来自其他计算机,可能被阻止以帮助保护该计算机/WORD在试图打开文件时遇到错误……
  6. linux 下mysql忘记密码或者安装好linux后不知道mysql初始密码解决方案
  7. PHP json_encode中文乱码解决方法
  8. SpringBoot2.X + SpringCache + redis解决乱码问题
  9. IEnumerable和使用收益回报的递归
  10. Android ADB设备离线,无法发出命令