web-dev-qa-db-fra.com

Comment utiliser NSString drawInRect pour centrer le texte?

Comment puis-je dessiner une NSString centrée dans une NSRect?

J'ai commencé avec: (un extrait de la méthode drawRect de ma vue personnalisée)

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

Maintenant, je suppose que je dois configurer certains attributs. J'ai consulté la documentation Apple sur Cocoa, mais elle est un peu lourde et ne trouve rien sur la manière d'ajouter des styles de paragraphe aux attributs.

De plus, je ne trouve que horizontal alignement, qu'en est-il de vertical alignement?

40
Steve Folly

Alignement vertical que vous devrez faire vous-même ((hauteur de vue + hauteur de chaîne)/2). Alignement horizontal que vous pouvez faire avec:

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

Cela fonctionne pour moi pour l'alignement horizontal

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

La réponse de Martins est assez proche, mais elle comporte quelques petites erreurs. Essaye ça:

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

Vous devrez créer un nouveau NSMutableParagraphStyle (au lieu d'utiliser le style de paragraphe par défaut, comme l'a suggéré Martin) car [NSMutableParagraphStyle defaultParagraphStyle] renvoie un NSParagraphStyle, qui ne possède pas la méthode setAlignment. De plus, vous n'avez pas besoin de la chaîne @"NSParagraphStyleAttributeName"— ___NSParagraphStyleAttributeName.

19
matthewwithanm

Cela fonctionne pour moi:

    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];
12
Dorin Grecu

[NSMutableParagraphStyle defaultParagraphStyle] ne fonctionnera pas, utilisez:

[NSMutableParagraphStyle new]

de plus, il semble que l'alignement horizontal ne fonctionne que pour drawInRect, pas drawAtPoint (demandez-moi comment je sais :-)

4
David H

Si vous êtes intéressé par une adaptation iOS7 +, déposez-le dans une catégorie 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
                                       }];
}
4
Kris

DrawInRect n’est bon que pour dessiner du texte de base (c’est-à-dire que le système décide où positionner votre texte) - souvent, la seule façon de dessiner un texte à l’endroit où vous voulez est de calculer simplement le point souhaité et d’utiliser drawAtPoint : withAttributes :.

En outre, sizeWithAttributes de NSString est extrêmement utile pour tout calcul de positionnement que vous devez faire pour drawAtPoint.

Bonne chance!

2
Joel Levin

Seulement pour iOS Swift 4 , Centrer la chaîne dans le rectangle en utilisant la méthode draw (in: withAttributes :)

let textFont = UIFont.boldSystemFont(ofSize: )
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
paragraphStyle.minimumLineHeight =  rectangle.height / 2 + textFont.lineHeight / 2
let textAttributes = [
            NSAttributedStringKey.font: textFont,
            NSAttributedStringKey.paragraphStyle: paragraphStyle
            ] as [NSAttributedStringKey : Any]
let text = "Text"
(text as NSString).draw(in: rectangle, withAttributes: textAttributes)
1
Malder

La bonne réponse est:

-drawInRect:withFont:lineBreakMode:alignment:

J'ai également créé une petite catégorie pour l'alignement vertical. Si vous aimez l'utiliser, allez-y :)

// 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
1
Julian F. Weinert

L'extrait suivant est utile pour dessiner une chaîne de texte centrale utilisant une image personnalisée Annotation comme référence:

CustomAnnotation.h

@interface CustomAnnotation : MKAnnotationView
[...]

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];


            }
        }
0
jalopezsuarez