问题
You can ask a UIFont
instance for its lineHeight
metric:
UIFont *const font = [UIFont systemFontOfSize: 10];
CGFloat lineHeight = [font lineHeight];
If I want a particular lineHeight, (20, say), how can I create a UIFont with that size?
回答1:
Answer
My limited analysis suggests, surprisingly to me, that linear interpolation can be used. Here's a category on UIFont
that will do what's needed:
@interface UIFont (FontWithLineHeight)
+(UIFont*) systemFontWithLineHeight: (CGFloat) lineHeight;
@end
With an implementation:
@implementation UIFont (FontWithLineHeight)
+(UIFont*) systemFontWithLineHeight:(CGFloat)lineHeight
{
const CGFloat lineHeightForSize1 = [[UIFont systemFontOfSize: 1] lineHeight];
const CGFloat pointSize = lineHeight / lineHeightForSize1;
return [UIFont systemFontOfSize: pointSize];
}
@end
Used like this:
UIFont *const font = [UIFont systemFontWithLineHeight: 20];
NSLog(@"%f", [font lineHeight]);
Which outputs:
2014-01-08 16:04:19.614 SpikeCollectionView[6309:60b] 20.000000
Which is what was asked for.
Analysis
It seems that the lineHeight
of a UIFont
scales linearly with the pointSize
. In other words, if you make the pointSize
twice as much, then the lineHeight
will be twice as much too. If you halve the pointSize
you also halve the lineHeight
. This means that interpolation can be used to find the pointSize
that will provide a given lineHeight
or other metric.
Here's code that shows the linearity:
const CGFloat lineHeight1 = [[UIFont systemFontOfSize: 1] lineHeight];
const CGFloat lineHeight10 = [[UIFont systemFontOfSize: 10] lineHeight];
const CGFloat lineHeight100 = [[UIFont systemFontOfSize: 100] lineHeight];
const CGFloat ratio1_10 = lineHeight10 / lineHeight1;
const CGFloat ratio10_100 = lineHeight100 / lineHeight10;
NSLog(@"%f", ratio1_10);
NSLog(@"%f", ratio10_100);
The output is:
2014-01-08 15:56:39.326 SpikeCollectionView[6273:60b] 9.999999
2014-01-08 15:56:39.329 SpikeCollectionView[6273:60b] 10.000001
Caution
I've only tested this for the system font on iOS 7. Other fonts may not exhibit linear scaling of their metrics under scalings to their pointSize. If someone could confirm whether this is guaranteed or when it won't work, that would be marvellous. If you try this for other UIFont
and it doesn't work, please comment or extend this answer, or add another.
If linear scaling of the metrics is not guaranteed, it would be necessary to search for the required pointSize
. You will need a "root finding" numeric algorithm. The Illinois Algorithm would work for this.
来源:https://stackoverflow.com/questions/21000864/how-can-i-find-the-uifont-pointsize-necessary-to-get-a-desired-lineheight-or-oth