objective-c 如何使用 NSString drawInRect 居中文本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/477509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:04:34  来源:igfitidea点击:

How to use NSString drawInRect to center text?

objective-ccocoamacos

提问by Steve Folly

How can I draw a NSStringcentered within a NSRect?

我怎样才能NSString在 a 内画一个居中的NSRect

I've started off with: (an extract from the drawRect method of my custom view)

我已经开始了:(从我的自定义视图的 drawRect 方法中摘录)

NSString* theString = ...
[theString drawInRect:theRect withAttributes:0];
[theString release];

Now I'm assuming I need to set up some attributes. I've had a look through Apple's Cocoa documentation, but it's a bit overwhelming and can't find anything for how to add paragraph styles to the attributes.

现在我假设我需要设置一些属性。我已经浏览了 Apple 的 Cocoa 文档,但它有点让人不知所措,找不到任何关于如何向属性添加段落样式的信息。

Also, I can only find horizontalalignment, what about verticalalignment?

另外,我只能找到水平对齐,垂直对齐呢?

回答by Martin Pilkington

Vertical alignment you'll have to do yourself ((height of view + height of string)/2). Horizontal alignment you can do with:

您必须自己进行垂直对齐((视图高度 + 字符串高度)/2)。您可以使用以下方法进行水平对齐:

NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
style.alignment = NSTextAlignmentCenter;
NSDictionary *attr = [NSDictionary dictionaryWithObject:style forKey:NSParagraphStyleAttributeName];
[myString drawInRect:someRect withAttributes:attr];

回答by Nikolay Klimchuk

This works for me for horizontal alignment

这适用于我的水平对齐

[textX drawInRect:theRect 
         withFont:font 
    lineBreakMode:UILineBreakModeClip 
        alignment:UITextAlignmentCenter];

回答by matthewwithanm

Martins answer is pretty close, but it has a few small errors. Try this:

Martins 的回答非常接近,但有一些小错误。尝试这个:

NSMutableParagraphStyle* style = [[NSMutableParagraphStyle alloc] init];
[style setAlignment:NSCenterTextAlignment];
NSDictionary *attr = 
  [NSDictionary dictionaryWithObject:style 
                              forKey:NSParagraphStyleAttributeName];
[myString drawInRect:someRect withAttributes:attr];
[style release];

You'll have to create a new NSMutableParagraphStyle(instead of using the default paragraph style as Martin suggested) because [NSMutableParagraphStyle defaultParagraphStyle]returns an NSParagraphStyle, which doesn't have the setAlignment method. Also, you don't need the string @"NSParagraphStyleAttributeName"—just NSParagraphStyleAttributeName.

您必须创建一个新的NSMutableParagraphStyle(而不是像 Martin 建议的那样使用默认的段落样式),因为[NSMutableParagraphStyle defaultParagraphStyle]返回一个NSParagraphStyle没有 setAlignment 方法的 。此外,您不需要字符串 —@"NSParagraphStyleAttributeName"只需要NSParagraphStyleAttributeName.

回答by Don Grem

This works for me:

这对我有用:

    CGRect viewRect = CGRectMake(x, y, w, h);
    UIFont* font = [UIFont systemFontOfSize:15];
    CGSize size = [nsText sizeWithFont:font
                     constrainedToSize:viewRect.size
                         lineBreakMode:(UILineBreakModeWordWrap)];  
    float x_pos = (viewRect.size.width - size.width) / 2; 
    float y_pos = (viewRect.size.height - size.height) /2; 
    [someText drawAtPoint:CGPointMake(viewRect.origin.x + x_pos, viewRect.origin.y + y_pos) withFont:font];

回答by David H

[NSMutableParagraphStyle defaultParagraphStyle]won't work use:

[NSMutableParagraphStyle defaultParagraphStyle]不会工作使用:

[NSMutableParagraphStyle new]

[NSMutableParagraphStyle new]

also, it appears horizontal alignment only works for drawInRect, not drawAtPoint(ask me how I know :-)

此外,似乎水平对齐仅适用于drawInRect,而不适用drawAtPoint(问我我怎么知道 :-)

回答by Kris

For anyone interested in an iOS7+ adaptation, drop this in an NSString category:

对于任何对 iOS7+ 改编感兴趣的人,请将其放在 NSString 类别中:

- (void)drawVerticallyInRect:(CGRect)rect withFont:(UIFont *)font color:(UIColor *)color andAlignment:(NSTextAlignment)alignment
{
    rect.origin.y = rect.origin.y + ((rect.size.height - [self sizeWithAttributes:@{NSFontAttributeName:font}].height) / 2);

    NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
    [style setAlignment:alignment];

    [self drawInRect:rect withAttributes:@{
                                       NSFontAttributeName              : font,
                                       NSForegroundColorAttributeName   : color,
                                       NSParagraphStyleAttributeName    : style
                                       }];
}

回答by Malder

For iOSSwift, To center String within the rectangle using the method draw(in:withAttributes:)

对于iOS Swift,使用draw(in:withAttributes:)方法在矩形内居中 String

func drawInCenter(_ text: String, into rectangle: CGRect, with textFont: UIFont) {
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.alignment = .center
    let rectangle = CGRect.zero
    paragraphStyle.minimumLineHeight = rectangle.height / 2 + textFont.lineHeight / 2
    let textAttributes = [NSAttributedString.Key.font: textFont,
                          NSAttributedString.Key.paragraphStyle: paragraphStyle] as [NSAttributedString.Key : Any]
    (text as NSString).draw(in: rectangle, withAttributes: textAttributes)
}

回答by Joel Levin

Well, drawInRect is only good for basic text drawing (in other words, the system decides where to position your text) - often the only way to draw text positioned where you want is to simply calculate what point you want it at and use NSString's drawAtPoint:withAttributes:.

嗯,drawInRect 只适用于基本的文本绘制(换句话说,系统决定放置文本的位置)——通常,绘制文本的唯一方法是简单地计算你想要的位置并使用 NSString 的 drawAtPoint :withAttributes:.

Also, NSString's sizeWithAttributes is hugely useful in any positioning math you end up having to do for drawAtPoint.

此外,NSString 的 sizeWithAttributes 在您最终必须为 drawAtPoint 执行的任何定位数学中都非常有用。

Good luck!

祝你好运!

回答by Julian F. Weinert

The correct answer is:

正确答案是:

-drawInRect:withFont:lineBreakMode:alignment:

-drawInRect:withFont:lineBreakMode:alignment:

I also created a small category for vertical alignment. If you like to use it, go ahead :)

我还为垂直对齐创建了一个小类别。如果您喜欢使用它,请继续:)

// NSString+NSVerticalAlign.h
typedef enum {
    NSVerticalTextAlignmentTop,
    NSVerticalTextAlignmentMiddle,
    NSVerticalTextAlignmentBottom
} NSVerticalTextAlignment;

@interface NSString (VerticalAlign)
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font verticalAlignment:(NSVerticalTextAlignment)vAlign;
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(NSLineBreakMode)lineBreakMode verticalAlignment:(NSVerticalTextAlignment)vAlign;
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment verticalAlignment:(NSVerticalTextAlignment)vAlign;
@end


// NSString+NSVerticalAlign.m
#import "NSString+NSVerticalAlign.h"

@implementation NSString (VerticalAlign)
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font verticalAlignment:(NSVerticalTextAlignment)vAlign {
switch (vAlign) {
    case NSVerticalTextAlignmentTop:
        break;

    case NSVerticalTextAlignmentMiddle:
        rect.origin.y = rect.origin.y + ((rect.size.height - font.pointSize) / 2);
        break;

    case NSVerticalTextAlignmentBottom:
        rect.origin.y = rect.origin.y + rect.size.height - font.pointSize;
        break;
    }
    return [self drawInRect:rect withFont:font];
}
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(NSLineBreakMode)lineBreakMode verticalAlignment:(NSVerticalTextAlignment)vAlign {
switch (vAlign) {
    case NSVerticalTextAlignmentTop:
        break;

    case NSVerticalTextAlignmentMiddle:
        rect.origin.y = rect.origin.y + ((rect.size.height - font.pointSize) / 2);
        break;

    case NSVerticalTextAlignmentBottom:
        rect.origin.y = rect.origin.y + rect.size.height - font.pointSize;
        break;
    }   
    return [self drawInRect:rect withFont:font lineBreakMode:lineBreakMode];
}
- (CGSize)drawInRect:(CGRect)rect withFont:(UIFont *)font lineBreakMode:(NSLineBreakMode)lineBreakMode alignment:(NSTextAlignment)alignment verticalAlignment:(NSVerticalTextAlignment)vAlign {
switch (vAlign) {
    case NSVerticalTextAlignmentTop:
        break;

    case NSVerticalTextAlignmentMiddle:
        rect.origin.y = rect.origin.y + ((rect.size.height - font.pointSize) / 2);
        break;

    case NSVerticalTextAlignmentBottom:
        rect.origin.y = rect.origin.y + rect.size.height - font.pointSize;
        break;
    }   
    return [self drawInRect:rect withFont:font lineBreakMode:lineBreakMode alignment:alignment];
}
@end

回答by jalopezsuarez

The following snippet is useful for drawing a center text string using an Annotation custom image as a reference:

以下代码段对于使用 Annotation 自定义图像作为参考绘制中心文本字符串很有用:

CustomAnnotation.h

自定义注释.h

@interface CustomAnnotation : MKAnnotationView
[...]

CustomAnnotation.m

CustomAnnotation.m

[...]        
       - (void)drawRect:(CGRect)rect
        {
            ClusterAnnotation *associatedAnnotation = (CustomAnnotation *)self.annotation;
            if (associatedAnnotation != nil)
            {
                CGContextRef context = UIGraphicsGetCurrentContext();

                NSString *imageName = @"custom_image.png";                
                CGRect contextRect = CGRectMake(0, 0, 42.0, 42.0);
                CGFloat fontSize = 14.0;        

                [[UIImage imageNamed:imageName] drawInRect:contextRect];

                NSInteger myIntegerValue = [associatedAnnotation.dataObject.myIntegerValue integerValue];
                NSString *myStringText = [NSString stringWithFormat:@"%d", myIntegerValue];

                UIFont *font = [UIFont fontWithName:@"Helvetica-Bold" size:fontSize];

                CGSize fontWidth = [myStringText sizeWithFont:font];

                CGFloat yOffset = (contextRect.size.height - fontWidth.height) / 2.0;
                CGFloat xOffset = (contextRect.size.width - fontWidth.width) / 2.0;        

                CGPoint textPoint = CGPointMake(contextRect.origin.x + xOffset, contextRect.origin.y + yOffset);        

                CGContextSetTextDrawingMode(context, kCGTextStroke);

                CGContextSetLineWidth(context, fontSize/10);
                CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] CGColor]);
                [myStringText drawAtPoint:textPoint withFont:font];

                CGContextSetTextDrawingMode(context, kCGTextFill);
                CGContextSetFillColorWithColor(context, [[UIColor blackColor] CGColor]);
                [myStringText drawAtPoint:textPoint withFont:font];


            }
        }