如何在UIImage指定位置渲染UILabel?及相关代码疑问解答
问题
我使用一段代码创建带自适应文字大小的图片,代码如下:
CGFloat size = 100.0; CGRect drawRect = CGRectMake(10, 10, 80, 25); UILabel *myLabel = [[UILabel alloc] initWithFrame:drawRect]; myLabel.font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:16]; myLabel.text = "Hello text!"; myLabel.minimumScaleFactor = 0.5; myLabel.adjustsFontSizeToFitWidth = YES; myLabel.textAlignment = NSTextAlignmentCenter; myLabel.backgroundColor = [UIColor clearColor]; UIGraphicsBeginImageContextWithOptions(CGSizeMake(size, size), NO, 0); [[myLabel layer] renderInContext:UIGraphicsGetCurrentContext()]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [screenshot drawInRect:drawRect]; return screenshot;
现在生成的100x100图片中,UILabel渲染在左上角(0,0)位置,我该如何将其置于目标位置(10,10)?补充说明:我希望Label保持指定尺寸、水平居中,且文字可根据可用空间自适应缩放。另外,[screenshot drawInRect:drawRect]的作用是什么?因为移除该行代码后结果似乎一致。
解决方案
一、调整Label到目标位置的方法
问题出在Layer渲染的坐标系逻辑:当你直接调用renderInContext:渲染Label的Layer时,它会以Label自身的坐标系原点(也就是Label自己的左上角)作为绘制起点,不会自动使用drawRect的原点坐标。要让Label画在100x100画布的(10,10)位置,只需在渲染前平移图形上下文的坐标系,修改后的完整代码如下:
CGFloat size = 100.0; CGRect drawRect = CGRectMake(10, 10, 80, 25); UILabel *myLabel = [[UILabel alloc] initWithFrame:drawRect]; myLabel.font = [UIFont fontWithName:@"HelveticaNeue-BoldItalic" size:16]; myLabel.text = "Hello text!"; myLabel.minimumScaleFactor = 0.5; myLabel.adjustsFontSizeToFitWidth = YES; myLabel.textAlignment = NSTextAlignmentCenter; myLabel.backgroundColor = [UIColor clearColor]; UIGraphicsBeginImageContextWithOptions(CGSizeMake(size, size), NO, 0); CGContextRef context = UIGraphicsGetCurrentContext(); // 平移上下文,让Label从(10,10)位置开始绘制 CGContextTranslateCTM(context, drawRect.origin.x, drawRect.origin.y); [[myLabel layer] renderInContext:context]; UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return screenshot;
这样修改后,Label会准确出现在画布的(10,10)位置,同时保持你设置的80x25尺寸,文字水平居中、自适应缩放的功能不受任何影响。
二、关于[screenshot drawInRect:drawRect]的作用
这行代码完全是冗余的,移除后结果一致是正常现象:
- 它的本意是将刚生成的
screenshot图片再次绘制到当前图形上下文,但此时你已经通过renderInContext:完成了Label的绘制,紧接着就会获取图片并结束上下文。 - 相当于在同一个位置重复绘制完全相同的内容,视觉上不会产生任何变化,所以可以直接删除这行代码。
内容的提问来源于stack exchange,提问作者meaning-matters
相关产品推荐
相关产品推荐

