Базовый текст - неправильная позиция текста

Я впервые использую основную графику и текст, поэтому могу делать что-то очень простое, что неверно. Я читал документацию, чтобы попытаться понять, в чем проблема, но не вижу, поэтому удивляюсь, может ли кто-нибудь помочь мне определить проблему.

Я пытаюсь нарисовать простой маленький баннер с информацией в верхней части экрана, но текст, который я хочу отобразить на баннере, нарисован не в правильном месте.

На мой взгляд, я создаю свой контроль следующим образом:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.banner = [[Banner alloc] initWithFrame:CGRectMake(0,20,768,200)];
    [self.view addSubview:self.banner];
}

Код управления выглядит следующим образом:

#import <CoreText/CoreText.h>

#import "Banner.h"

@implementation Banner

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        self.backgroundColor = [UIColor colorWithRed:0.9 green:0.9 blue:0.9 alpha:1];
    }
    return self;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Get the graphics context.
    CGContextRef context = UIGraphicsGetCurrentContext();

    // Draw the banner border.
    CGContextSaveGState(context);

    UIColor *strokeColor = [UIColor blackColor];
    CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);
    CGContextSetLineWidth(context, 5);
    CGContextStrokeRect(context, CGRectMake(2,2,self.frame.size.width -4,100));

    CGContextRestoreGState(context);


    // Setup the text label & value.
    NSString *addressLabelText = @"Address";
    NSString *addressValue = @"123 Letsby Avenue\nSome Place\nSome City\nSome County\nSome Postcode";

    UIFont *font = [UIFont fontWithName:@"Helvetica" size:14.0];

    CGSize labelSize = [self getBoundsForString:addressLabelText usingFont:font];
    CGSize valueSize = [self getBoundsForString:addressValue usingFont:font];

    // So I want to Draw the label at X:10 Y:10 and the Value At X:65 Y:10
    // So we get Something like:
    // =============================
    // || Address 123 letsby avenue
    // ||         Some Place
    // ||         Some City
    // ||         Some County
    // ||         Some Postcode
    // =============================

    CGRect labelBounds = CGRectMake(10,10,labelSize.width,labelSize.height);
    // Move the address value over the margin width(10) + the label width + some spacing(5)
    CGRect valueBounds = CGRectMake(10 + labelSize.width + 5, 10, valueSize.width, valueSize.height);

    [self drawString: addressLabelText withFont: font inRect:labelBounds usingContext:context];
    [self drawString: addressValue withFont: font inRect:valueBounds usingContext:context];

    // The text hasn't drawn where i thought it should. Draw a rect there to make sure i had the right bounds
    UIColor *rectFillColor = [UIColor colorWithRed:0 green:0 blue:1 alpha:0.3];

    CGContextSaveGState(context);

    CGContextSetFillColorWithColor(context, [rectFillColor CGColor]);
    CGContextFillRect(context, labelBounds);
    CGContextFillRect(context, valueBounds);

    CGContextRestoreGState(context);
    //Hmm that is drawing in the right place. Whats going wrong with drawing the text.

    [self setNeedsDisplay];

}

-(void) drawString:(NSString*) string withFont:(UIFont*)font inRect:(CGRect)rect usingContext:(CGContextRef) context
{
    CGContextSaveGState(context);

    // flipping the coordinate system.
    CGContextTranslateCTM(context, 0, 200); // The control is rendered in a frame 200 high.
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

    // Define the path we are going to draw the text on.
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, NULL, rect);

    CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
    CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef)string);

    // Create the framesetter with the attributed string.
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
    CFRelease(attrString);

    // Create a frame.
    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

    // Draw the specified frame in the given context.
    CTFrameDraw(frame, context);

    CGContextRestoreGState(context);

    CFRelease(frame);
    CFRelease(path);
    CFRelease(framesetter);
}

-(CGSize) getBoundsForString:(NSString *)string usingFont:(UIFont *)font
{
    return [string boundingRectWithSize:CGSizeMake(999,999)
                   options:NSStringDrawingUsesLineFragmentOrigin
                   attributes:[NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName]
                   context:nil].size;
}


@end

В результате на баннере нарисованы синие штрихи, где я ожидал, что текст будет, но текст на самом деле появляется за пределами баннера, и я озадачен, почему.

https://www.dropbox.com/s/q2ap9tl4okaka49/Banner.png

1 ответ

Решение

Я нашел то, что работает для моего кода выше... изменив это:

-(void) drawString:(NSString*) string withFont:(UIFont*)font inRect:(CGRect)rect usingContext:(CGContextRef) context
{
    CGContextSaveGState(context);

    // flipping the coordinate system.
    CGContextTranslateCTM(context, 0, 200); // The control is rendered in a frame 200 high.
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

в

-(void) drawString:(NSString*) string withFont:(UIFont*)font inRect:(CGRect)rect usingContext:(CGContextRef) context
{
    CGContextSaveGState(context);

    // flipping the coordinate system.
    CGContextTranslateCTM(context, 0, rect.size.height+(2*rect.origin.y));
    CGContextScaleCTM(context, 1.0, -1.0);

Строка, следующая за строкой, похоже, ничего не меняет.

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

И меняем эту строку:

    CGContextTranslateCTM(context, 0, 200);

в

    CGContextTranslateCTM(context, 0, rect.size.height+(2*rect.origin.y));

помещает текст правильно, где я ожидал бы это.... используя Xamarin и эквивалентный C# Я должен инвертировать результат высоты + 2Y результат:-S

Другие вопросы по тегам