iOS Objective-C中用Quartz 2D实现PDF评论区文本分行排版的方法
解决Core Graphics PDF评论区逐行文本控制问题
看起来你现在的问题是没法对评论区的每一行文本单独控制,对吧?我看了你的代码,问题出在你把整个评论文本一次性绘制到一个大的rect里了——系统自动帮你换行,但这样你没法精准控制每一行的位置、样式,也没法和你手动画的那些横线对应上。下面给你两种实用的解决方案:
方案一:手动拆分文本逐行绘制
这种方法适合简单场景,能精准把每一行文本对齐你画的横线,还能单独控制每一行的内容和样式:
// 你的原始评论文本 NSString *commentText = @"helo how are you. i am tuna string. i have so many friends. helllo i am working.here is my paragraph writing"; // 假设fontName2是你的字体名称,这里初始化字体 UIFont *newfont = [UIFont fontWithName:fontName2 size:7]; // 横线之间的间距(你画的横线从155到170,间距15) CGFloat lineSpacing = 15; // 第一行文本的起始Y坐标 CGFloat currentY = 146; // 文本区域的宽度(横线从20到295,文本从62开始,所以宽度是295-62=233) CGFloat textLineWidth = 295 - 62; // 用可变字符串存储剩余未绘制的文本 NSMutableString *remainingText = [commentText mutableCopy]; // 逐行处理文本 while (remainingText.length > 0 && currentY <= 200) { // 200是最后一条横线的Y坐标,防止超出范围 // 计算当前行能容纳的文本范围 CGRect textBounds = [remainingText boundingRectWithSize:CGSizeMake(textLineWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: newfont} context:nil]; // 找到第一个换行的空格位置,避免单词被截断 NSRange spaceRange = [remainingText rangeOfString:@" " options:0 range:NSMakeRange(0, textBounds.size.width)]; NSInteger lineEndIndex = (spaceRange.location != NSNotFound) ? spaceRange.location : remainingText.length; // 截取当前行的文本 NSString *currentLineText = [remainingText substringToIndex:lineEndIndex]; // 绘制当前行到对应位置 CGRect lineRect = CGRectMake(62, currentY, textLineWidth, lineSpacing); [currentLineText drawInRect:lineRect withFont:newfont lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentLeft]; // 更新剩余文本和下一行的Y坐标 [remainingText deleteCharactersInRange:NSMakeRange(0, lineEndIndex)]; currentY += lineSpacing; }
方案二:用NSAttributedString + 布局管理器(更灵活)
如果需要更复杂的样式控制(比如某一行加粗、变色),或者要处理更复杂的文本布局,推荐用Text Kit的组件来实现,能更精准地控制每一行:
NSString *commentText = @"helo how are you. i am tuna string. i have so many friends. helllo i am working.here is my paragraph writing"; UIFont *newfont = [UIFont fontWithName:fontName2 size:7]; // 创建带属性的文本,这里可以给不同段落/行设置不同样式 NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:commentText attributes:@{ NSFontAttributeName: newfont, NSForegroundColorAttributeName: [UIColor blackColor] }]; // 比如给某一行设置加粗: // [attributedText addAttribute:NSFontAttributeName value:[UIFont boldSystemFontOfSize:7] range:NSMakeRange(0, 10)]; // 初始化Text Kit组件 NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init]; NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(295-62, CGFLOAT_MAX)]; textContainer.lineFragmentPadding = 0; // 去掉默认的内边距 [layoutManager addTextContainer:textContainer]; NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedText]; [textStorage addLayoutManager:layoutManager]; // 逐行绘制文本 NSUInteger glyphIndex = 0; CGFloat currentY = 146; CGFloat lineSpacing = 15; while (glyphIndex < layoutManager.numberOfGlyphs && currentY <= 200) { CGRect lineFragmentRect; // 获取当前行的字形范围和位置 NSRange lineGlyphRange = [layoutManager lineFragmentRectForGlyphAtIndex:glyphIndex effectiveRect:&lineFragmentRect]; // 调整行的位置到你的横线对应位置 CGPoint drawPoint = CGPointMake(62, currentY); // 绘制当前行 [layoutManager drawGlyphsForGlyphRange:lineGlyphRange atPoint:drawPoint]; // 更新索引和Y坐标 glyphIndex = NSMaxRange(lineGlyphRange); currentY += lineSpacing; }
为什么原来的方法不行?
你之前用[commentText drawInRect:...]把整个文本放进一个大rect,系统会自动换行,但这种方式是“黑盒”的——你没法控制每一行的具体位置,也没法单独修改某一行的样式,更没法保证文本和你手动画的横线精准对齐。上面的两种方法都是把文本拆分成单独的行,让你能完全掌控每一行的绘制。
内容的提问来源于stack exchange,提问作者Jezebel Smith
相关产品推荐
相关产品推荐

