drawInRect: withAttributes text center vertically or put some padding

11,440

Solution 1

First you need to calculate the height of the text, with this information and the height of your bounding rectangle, you can easily compute the new rectangle to center the text.

I will share a piece of code I use to center vertically. In my case I use a different drawInRect function (drawInRect:withFont...) and I use sizeWithFont to calculate the size of the text. YOu would either adapt this code to use the functions you're already using (with attributes), or either use the functions I'm posting here.

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

Solution 2

Here's how to do it in iOS 8 (or 7+) based on @Merlevede's answer with a correction and using new 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];

Solution 3

Swift 3 solution:

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)
    }
}

Solution 4

Swift version in form of the extension, based on @WillLarche and @Merlevede answers.

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)
    }
}

Usage

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

P.S. I know that name of method could be better ;)

Solution 5

Swift 4 Solution:

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)
    }
}
Share:
11,440
Madhu
Author by

Madhu

Updated on June 18, 2022

Comments

  • Madhu
    Madhu almost 2 years

    I'm using drawInRect : withAttributes to add text to a pdf in iOS 7. I need to vertically center the text inside the CGRect or at least I need to keep some gap/padding between the CGRect border and text. Otherwise text look too closer to the box. Is there any attribute to do that? If not what is the best way to do that? Below is my code.
    I tried NSBaselineOffsetAttributeName , but it only increases the gap between each line, but not the gap to the border of the rect.
    Thanks

     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];
    
  • Madhu
    Madhu about 10 years
    Thanks I'll try this. But I tried something similar earlier by changing the y position, then the whole rectangle came down. Not just the text. May be I did something wrong. I'll try this again and see.
  • Merlevede
    Merlevede about 10 years
    @Madhu The resulting rect would be used only to draw the text, not the bounding rectangle, otherwise you get the effect that you describe.
  • Madhu
    Madhu about 10 years
    Thanks. Got it working. I couldn't use your code, because these methods are deprecated in iOS 7. But I implemented your concept :-) Thanks for the help.