我找到了关于如何使用NSString drawInRect:绘制旋转文本的答案,但我不确定它是如何工作的,因为它只对我有用:https://discussions.apple.com/thread/1779814?start=0&tstart=0
我的代码如下:
CGContextSaveGState(context);
CGContextDrawLinearGradient(context, gradient, CGPointMake(0, centY - halfWidth), CGPointMake(0, centY + halfWidth), 0);
// Add text
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
NSString *str = @"some test string";
CGAffineTransform transform1 = CGAffineTransformMakeRotation(M_PI/4);
CGContextConcatCTM(context, transform1);
CGContextTranslateCTM(context, 0, 0);
UIFont *font = [UIFont systemFontOfSize:16.0];
[str drawInRect:CGRectMake(0, 0, 200, 100) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UIBaselineAdjustmentNone];
因此,当我使用它时,我看到文本被绘制在x轴下方45度处。我想沿着lineargradient垂直绘制文本。所以我认为我可以通过使用M_PI / 2 90度来做到这一点。我没看到我的文字。我已经为旋转尝试了不同的变换,只有一些似乎像M_PI / 4和M_PI / 8一样工作。我认为如果我使用-M_PI / 4,它将使文本在x轴上方45度,而M_PI / 2将在x轴下方90度。但两者都没有出现。
有什么想法?感谢。
答案 0 :(得分:18)
我以下一个方式解决了这个问题。
1)在NSString上声明类别
@interface NSString (NMSchemeItemDraw)
-(void) drawWithBasePoint:(CGPoint)basePoint
andAngle:(CGFloat)angle
andFont:(UIFont*)font;
@end
此类别将使用给定的中心点绘制文本,在一行中并使用给定的字体和角度。
2)此类别的实施如下:
@implementation NSString (NMSchemeItemDraw)
-(void) drawWithBasePoint:(CGPoint)basePoint
andAngle:(CGFloat)angle
andFont:(UIFont *)font{
CGSize textSize = [self sizeWithFont:font];
CGContextRef context = UIGraphicsGetCurrentContext();
CGAffineTransform t = CGAffineTransformMakeTranslation(basePoint.x, basePoint.y);
CGAffineTransform r = CGAffineTransformMakeRotation(angle);
CGContextConcatCTM(context, t);
CGContextConcatCTM(context, r);
[self drawAtPoint:CGPointMake(-1 * textSize.width / 2, -1 * textSize.height / 2)
withFont:font];
CGContextConcatCTM(context, CGAffineTransformInvert(r));
CGContextConcatCTM(context, CGAffineTransformInvert(t));
}
@end
3)现在我可以在我的[UIView drawRect:]
方法中使用它。
例如,在下一个方面:
-(void)drawRect:(CGRect)rect{
NSString* example = @"Title";
[example drawWithBasePoint:CGPointMake(0.0f, 0.0f)
andAngle:M_PI
andFont:[UIFont boldSystemFontOfSize:16.0]];
}
答案 1 :(得分:12)
我认为发生的事情是您将文本旋转到视图外部的位置,因为它通过在原点上旋转来旋转上下文。
旋转后,您需要进行翻译以将上下文移回视图。在下面的示例中,我将上下文逆时针旋转90度。然后我翻译上下文的tx高度的距离。
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Create the gradient
CGColorRef startColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor;
CGColorRef endColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:1.0].CGColor;
NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil];
CGFloat locations[] = { 0.0, 1.0 };
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef) colors, locations);
CGContextDrawLinearGradient(context, gradient, CGPointMake(rect.origin.x + rect.size.width / 2, rect.origin.y), CGPointMake(rect.origin.x + rect.size.width / 2, rect.origin.y + rect.size.height), 0);
// Create text
CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
NSString *string = @"some test string";
UIFont *font = [UIFont systemFontOfSize:16.0];
// Rotate the context 90 degrees (convert to radians)
CGAffineTransform transform1 = CGAffineTransformMakeRotation(-M_PI_2);
CGContextConcatCTM(context, transform1);
// Move the context back into the view
CGContextTranslateCTM(context, -rect.size.height, 0);
// Draw the string
[string drawInRect:rect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft];
// Clean up
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
CGContextRestoreGState(context);
}
请注意,您还可以获取字符串呈现方式的大小,这有助于计算文本的对齐方式。
CGSize stringSize = [string sizeWithFont:font];
答案 2 :(得分:9)
这是KoNEW答案的更新和简化版本。它保留了图形上下文的状态作为奖励。这也是一个简单的函数,而不是String扩展。
func drawRotatedText(_ text: String, at p: CGPoint, angle: CGFloat, font: UIFont, color: UIColor) {
// Draw text centered on the point, rotated by an angle in degrees moving clockwise.
let attrs = [NSFontAttributeName: font, NSForegroundColorAttributeName: color]
let textSize = text.size(attributes: attrs)
let c = UIGraphicsGetCurrentContext()!
c.saveGState()
// Translate the origin to the drawing location and rotate the coordinate system.
c.translateBy(x: p.x, y: p.y)
c.rotate(by: angle * .pi / 180)
// Draw the text centered at the point.
text.draw(at: CGPoint(x: -textSize.width / 2, y: -textSize.height / 2), withAttributes: attrs)
// Restore the original coordinate system.
c.restoreGState()
}
答案 3 :(得分:1)
感谢此帖,以及Chris's answer和Arkadiusz's answer at another post。
最后,我通过名为UILabel
的{{1}}子类解决了这个问题,并使其绘制垂直文本。
MyVerticalLabel
答案 4 :(得分:0)
我发现上面 Todd 的回答非常有帮助。但是,我经常想相对于文本的边缘之一(顶部、左侧等)定位和旋转文本。所以,我扩展了他的回答。另外,使用了属性文本,所以可以独立处理字体、颜色等。
enum StringOrigin: Int { case
upperLeft, upperCenter, upperRight,
centerLeft, centerCenter, centerRight,
lowerLeft, lowerCenter, lowerRight }
func drawRotatedAttrString(_ s: NSAttributedString, p: CGPoint, angle: CGFloat, origin: StringOrigin) {
let width = s.size().width
let height = s.size().height
let c = UIGraphicsGetCurrentContext()!
c.saveGState()
// Translate the origin to the drawing location and rotate the coordinate system.
c.translateBy(x: p.x, y: p.y)
c.rotate(by: angle * .pi / 180)
// Draw the text offset to handle "origin" choice
switch origin {
case .upperLeft:
s.draw(at: .zero)
case .upperCenter:
s.draw(at: CGPoint(x: -0.5 * width, y: 0))
case .upperRight:
s.draw(at: CGPoint(x: -width, y: 0))
case .centerLeft:
s.draw(at: CGPoint(x: 0, y: -0.5 * height))
case .centerCenter:
s.draw(at: CGPoint(x: -0.5 * width, y: -0.5 * height))
case .centerRight:
s.draw(at: CGPoint(x: -width, y: -0.5 * height))
case .lowerLeft:
s.draw(at: CGPoint(x: 0, y: -height))
case .lowerCenter:
s.draw(at: CGPoint(x: -0.5 * width, y: -height))
case .lowerRight:
s.draw(at: CGPoint(x: -width, y: -height))
}
// Restore the original coordinate system.
c.restoreGState()
}