How to use NSString's sizeWithFont and drawInR

2019-02-04 03:21发布

I'm drawing multiple 'pages' of imagery using a CGContext in the iOS. I've used sizeWithFont and drawInRect combinations extensively in my app. What I need to do is split a large chunk of text across multiple pages. I can size it and work out whether or not it needs another page but how do I know where to chop it? Do I have to do an ugly loop to check word by word until I find a string length that perfectly fits the page and then chop the string at that point? Is there a smarter way?

Any ideas?

Thanks.

2条回答
干净又极端
2楼-- · 2019-02-04 03:26

The NSString additions to UIKit for drawing text, you can pre-determine the exact amount of space required to render a given text for a given font. If splitting the text into pages, you could use this method.

– sizeWithFont:constrainedToSize:lineBreakMode:

Assuming the font and line break mode is known, create a CGSize having the same width as your page, and use a sufficiently number for height. This would be the maximum size that we are constraining the text into.

CGSize maximumSize = CGSizeMake(pageWidth, 999999999);
CGSize expectedSize = [veryLongString sizeWithFont:theFont constrainedToSize:maximumSize lineBreakMode:theLineBreakMode];

expectedSize will tell us the size that the text will take assuming if it could extend vertically infinitely (well close to). To find the number of pages required, just divide the total height by the height of one page.

NSInteger totalPages = ceil(expectedSize.height / heightOfOnePage);

You would also want to adjust the height of one page to make sure that the last line of text doesn't get clipped. For that to happen, the height of the page should be a multiple of the font's line height. Say the initial page height is 300px, and the font-height is 16px, then there will be some clipping as 300/16 = 18.75 which is not a whole number.

NSInteger linesWithoutClipping = floor(initialPageHeight / theFont.lineHeight);
CGFloat optimalPageHeight = linesWithoutClipping * theFont.lineHeight;

Taking the floor value 18 and multiplying with the font line height 16, we get an optimal page height of 288 to ensure there's no clipping.

Note that lineHeight was introduced in iOS 4.0, but you could calculate it yourselves if needed for older versions.

查看更多
相关推荐>>
3楼-- · 2019-02-04 03:53

The way I get around this problem is to split by line returns.

NSArray * paragraphs = [text componentsSeparatedByString:@"\n"];

You still have to do all the work to determine page breaks and alike but I have found this the best workaround so far.

查看更多
登录 后发表回答