How can I find the UIFont pointSize necessary to get a desired lineHeight or other metric?

家住魔仙堡 提交于 2021-01-28 03:02:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!