6

I'm trying to indent the text in a UILabel to leave some margin around the text showing the background colour. Following the suggestion here I've overriden textRectForBounds:limitedToNumberOfLines: like so:

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
    CGRect intermediate = CGRectMake(bounds.origin.x+MARGIN,bounds.origin.y+MARGIN,bounds.size.width-2*MARGIN,bounds.size.height-2*MARGIN);
    return [super textRectForBounds:intermediate limitedToNumberOfLines:numberOfLines];
}

But no matter what I do, the text ends up tight against the left border of the rectangle. It seems as though the drawing is ignoring the origin part of the returned CGRect (although it seems to be respecting the width part, as if I reduce to width of intermediate to eg bounds.size.width-200 the rect that textRectForBounds returns is suitably narrow and the text is drawn in a long skinny column).

So: what else I need to do to the UILabel to make the drawing respect the textForRectBounds-returned-rect's origin.x and origin.y? I'd rather not override UILabel's drawTextInRect if I can help it.

Update: This was a long time ago and I can't remember exactly why the other question didn't work for me. I believe it was because I was trying to have a UILabel with multiple lines, and the solution here didn't work in that case.

Community
  • 1
  • 1
damian
  • 3,604
  • 1
  • 27
  • 46

2 Answers2

8

I think you should override both textRectForBounds:limitedToNumberOfLines: and drawTextInRect: like this:

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
    return CGRectInset(bounds, MARGIN, MARGIN);
}

- (void)drawTextInRect:(CGRect)rect
{
    [super drawTextInRect: CGRectInset(self.bounds, MARGIN, MARGIN)];
}
Costique
  • 23,712
  • 4
  • 76
  • 79
  • Thanks, this worked (more or less): I had to do some tweaking to the rect width to make things work properly with multiple lines, but I got it working in the end. – damian Feb 06 '11 at 08:30
  • If you do this (in order to match a UITextView) you may also want to override sizeThatFits like this: - (CGSize)sizeThatFits:(CGSize)size { CGSize fSize = [super sizeThatFits:size]; fSize.width += 2* MARGIN; fSIze.height += 2 * MARGIN; return fSize; } – Arie Litovsky Aug 31 '12 at 23:13
  • 1
    Doesn't work for me, it still doesn't get called. – Iulian Onofrei Aug 31 '17 at 13:42
0

Check the documentation, it might be of some help. calls to super might not be returning the values you assume.

You should not call this method directly. This method should only be overridden by subclasses that want to change the receiver’s bounding rectangle before performing any other computations. Use the value in the numberOfLines parameter to limit the height of the returned rectangle to the specified number of lines of text. For this method to be called, there must be a prior call to the sizeToFit or sizeThatFits: method. Note that labels in UITableViewCell objects are sized based on the cell dimensions, and not a requested size The default implementation of this method returns the original bounds rectangle.

Good luck!

Pacu
  • 1,985
  • 20
  • 33
  • 1
    Actually, the documentation is incorrect with `limitedToNumberOfLines:0`. The passed in `bounds` has a `height` that looks like `INT_MAX_VALUE` or something, and the default implementation seems to reduce it to a rect high enough to fit the text. – damian Feb 06 '11 at 08:34