DrawInRect: с текстовым центром Aтрибутов по вертикали или поместить некоторые дополнения

Я использую drawInRect: withAttributes, чтобы добавить текст в pdf в iOS 7. Мне нужно вертикально центрировать текст внутри CGRect или, по крайней мере, мне нужно сохранить пробел/дополнение между границей CGRect и текстом. В противном случае текст выглядит слишком близко к коробке. Есть ли какой-нибудь атрибут? Если не лучший способ сделать это? Ниже мой код.
Я пробовал NSBaselineOffsetAttributeName, но это только увеличивает разрыв между каждой строкой, но не разрыв с границей прямоугольника.
Благодаря

 CGContextRef    currentContext = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(currentContext, bgColor.CGColor);
CGRect renderingRect = CGRectMake(startPoint.x, startPoint.y, width, height);
CGContextFillRect(currentContext, renderingRect);

NSDictionary *attributes = @{ NSFontAttributeName: font,
                              NSForegroundColorAttributeName: fgColor,
                              };

[textToDraw drawInRect:renderingRect  withAttributes:attributes];

Ответ 1

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

Я поделюсь куском кода, который я использую, чтобы центрировать по вертикали. В моем случае я использую другую функцию drawInRect (drawInRect: withFont...), и я использую sizeWithFont для вычисления размера текста. Вы бы либо адаптировали этот код для использования функций, которые вы уже используете (с атрибутами), либо используете функции, которые я публикую здесь.

UIFont *font = [UIFont systemFontOfSize:14];
CGSize size = [text sizeWithFont:font];
if (size.width < rect.size.width)
{
    CGRect r = CGRectMake(rect.origin.x, 
                          rect.origin.y + (rect.size.height - size.height)/2, 
                          rect.size.width, 
                          (rect.size.height - size.height)/2);
    [text drawInRect:r withFont:font lineBreakMode:UILineBreakModeClip alignment:UITextAlignmentLeft];
}

Ответ 2

Вот как это сделать в iOS 8 (или 7+) на основе ответа @Merlevede с исправлением и использованием нового API:

    NSString *string = ....
    NSDictionary *attributes = ....
    CGSize size = [string sizeWithAttributes:attributes];

    CGRect r = CGRectMake(rect.origin.x,
                          rect.origin.y + (rect.size.height - size.height)/2.0,
                          rect.size.width,
                          size.height);


    [string drawInRect:r withAttributes:attributes];

Ответ 3

Решение Swift 3:

extension NSString {
    func drawVerticallyCentered(in rect: CGRect, withAttributes attributes: [String : Any]? = nil) {
        let size = self.size(attributes: attributes)
        let centeredRect = CGRect(x: rect.origin.x, y: rect.origin.y + (rect.size.height-size.height)/2.0, width: rect.size.width, height: size.height)
        self.draw(in: centeredRect, withAttributes: attributes)
    }
}

Ответ 4

Быстрая версия в форме расширения на основе ответов @WillLarche и @Merlevede.

extension CGRect {
    func verticalCenteredRectForString(string:NSString,withAttributes attributes : [String:AnyObject])->CGRect {
        let size = string.sizeWithAttributes(attributes)
        return CGRectMake(self.origin.x, self.origin.y + (self.size.height-size.height)/2.0 , self.size.width, size.height)
    }
}

Использование

let myString = NSString(string:"Some text")
let centeredRect = customRect.verticalCenteredRectForString(myString,attrParams)
myString.drawInRect(centereRect, withAttributes : attrParams)

P.S. Я знаю, что имя метода может быть лучше;)

Ответ 5

Решение Swift 4:

extension NSString {

    func drawVerticallyCentered(in rect: CGRect, withAttributes attributes: [NSAttributedStringKey : Any]? = nil) {
        let size = self.size(withAttributes: attributes)
        let centeredRect = CGRect(x: rect.origin.x, y: rect.origin.y + (rect.size.height-size.height)/2.0, width: rect.size.width, height: size.height)
        self.draw(in: centeredRect, withAttributes: attributes)
    }
}