iOS13.7中drawInRect绘制带描边NSString时换行错位问题
iOS13.7 描边文本与填充文本换行不匹配问题分析
这确实是iOS13.7的系统Bug。当设置了NSParagraphStyleAttributeName时,绘制带描边(NSStrokeWidthAttributeName)的文本和普通填充文本时,换行计算逻辑不一致,导致两者换行位置错位;而iOS14及后续版本修复了这个排版计算的问题。
问题原因
iOS13.7中,同时配置段落样式和描边属性时,文本布局引擎对换行宽度的计算存在偏差:描边文本会把描边宽度纳入换行宽度计算,填充文本仅计算字符本身宽度,最终导致两次绘制的文本换行位置不匹配。移除段落样式后,布局逻辑回退到默认处理,因此换行恢复一致。
解决方案
- 针对iOS13.x版本单独适配:不设置段落样式,通过计算文本宽度手动调整绘制起点来实现居中效果
- 改用一次性绘制方案:构建包含描边和填充的富文本,一次性完成绘制,避免两次绘制的布局偏差
- 若兼容范围允许,可直接依赖iOS14+的修复,不再针对iOS13.7做特殊适配
中文注释版代码
- (void)viewDidLoad { [super viewDidLoad]; // 绘制带描边的文本并转为图片 UIImage *img = [[self class] drawTextWithStroke]; // 创建图片视图并添加到当前页面 UIImageView* imageView = [[UIImageView alloc] initWithImage:img]; [self.view addSubview:imageView]; } + (UIImage*)drawTextWithStroke { // 待绘制的目标文本 NSString* string = @"The operation couldn’t be completed. completed"; // 定义文本绘制的矩形区域 CGRect rect = CGRectMake(0, 0, 362, 42); CGSize size = CGSizeMake(rect.size.width, rect.size.height); // 设置字体为Arial粗体,字号18 UIFont *font = [UIFont fontWithName:@"Arial-BoldMT" size:18]; // 适配Retina屏幕,启用两倍分辨率绘图 if ([UIScreen instancesRespondToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2.0f) { UIGraphicsBeginImageContextWithOptions(size, NO, 2.0f); } else { UIGraphicsBeginImageContext(size); } CGContextRef context = UIGraphicsGetCurrentContext(); // 创建可变字典用于存储文本样式属性 NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; // 配置段落样式:设置文本居中对齐 NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init]; [style setAlignment: NSTextAlignmentCenter]; attributes[ NSParagraphStyleAttributeName ] = style; // 绘制文本描边:设置字体、描边宽度为3、描边颜色为红色 [attributes setObject:font forKey:NSFontAttributeName]; [attributes setObject:[NSNumber numberWithFloat:3] forKey:NSStrokeWidthAttributeName]; [attributes setObject:[UIColor redColor] forKey:NSStrokeColorAttributeName]; [string drawInRect:rect withAttributes:attributes]; // 绘制文本填充:移除描边相关属性,设置填充颜色为黑色 [attributes removeObjectForKey:NSStrokeWidthAttributeName]; [attributes removeObjectForKey:NSStrokeColorAttributeName]; [attributes setObject:[UIColor blackColor] forKey:NSForegroundColorAttributeName]; [string drawInRect:rect withAttributes:attributes]; // 从当前绘图上下文提取图片并返回 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return newImage; }
内容的提问来源于stack exchange,提问作者Xt Z
相关产品推荐
相关产品推荐

