我需要使用iOS的系统字体" Hiragino Sans W3"在我的应用中,但无论我选择哪种尺寸/样式或UILabel
尺寸,字体的上升和下降始终会被剪裁:
这似乎可以通过创建UILabel
的子类并覆盖方法textRectForBounds:limitedToNumberOfLines:
来修复"更正"值。所以下面的代码......
- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines
{
CGRect result = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];
result = CGRectInset(result, 0, -5);
return result;
}
...导致ascender和descenders不再被剪裁:
我知道也可以使用外部编辑器调整字体上升和下降位置。 但这是一个系统字体,如果没有任何修改,它是否应该正常工作?我在这里找不到什么东西?
提前感谢您的任何答案。
答案 0 :(得分:1)
我认为这个问题实际上归结为字体本身(“Hiragino Sans”)。使用字体编辑器可以看到字形超出了上升和下降值,iOS似乎将其视为显示文本的垂直“边界框”。
由于缺乏更好的解决方案,我一直在使用(非常丑陋)黑客修改UIFont
只读属性ascender
和lineHeight
的值。
档案UIFont+Alignment.h
:
#import <UIKit/UIKit.h>
@interface UIFont (Alignment)
- (void)ensureCorrectFontAlignment;
@end
档案UIFont+Alignment.m
:
#import "UIFont+Alignment.h"
#import <objc/runtime.h>
#import <objc/message.h>
static NSHashTable *adjustedFontsList;
@implementation UIFont (Alignment)
- (void)ensureCorrectFontAlignment
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
adjustedFontsList = [NSHashTable hashTableWithOptions:NSHashTableWeakMemory];
});
@synchronized (adjustedFontsList) {
if ([adjustedFontsList containsObject:self]) {
return;
}
else if ([self.fontName containsString:@"Hiragino"]) {
SEL originalAscenderSelector = @selector(ascender);
Method originalAscenderMethod = class_getInstanceMethod([UIFont class], originalAscenderSelector);
SEL originalLineHeightSelector = @selector(lineHeight);
Method originalLineHeightMethod = class_getInstanceMethod([UIFont class], originalLineHeightSelector);
id result = method_invoke(self, originalAscenderMethod, nil);
CGFloat originalValue = [[result valueForKey:@"ascender"] floatValue];
[result setValue:@(originalValue * 1.15) forKey:@"ascender"];
result = method_invoke(self, originalLineHeightMethod, nil);
originalValue = [[result valueForKey:@"lineHeight"] floatValue];
[result setValue:@(originalValue * 1.25) forKey:@"lineHeight"];
[adjustedFontsList addObject:self];
}
}
}
@end
要应用,只需导入标题并在创建新的字体实例后调用[myUIFont ensureCorrectFontAlignment]
。
答案 1 :(得分:1)
@DPR 's answer帮助了我,但我遇到了错误
函数调用的参数过多,应为0,有2个method_invoke
我替换了
id result = method_invoke(self, originalAscenderMethod, nil);
与
id (*function)(id, Method) = (id (*)(id, Method)) method_invoke;
id result = function(self, originalAscenderMethod);
还有
result = method_invoke(self, originalLineHeightMethod, nil);
使用
result = function(self, originalLineHeightMethod);
答案 2 :(得分:1)
使用方法刷新的快速版本:
extension UIFont {
static func swizzle() {
method_exchangeImplementations(
class_getInstanceMethod(self, #selector(getter: ascender))!,
class_getInstanceMethod(self, #selector(getter: swizzledAscender))!
)
method_exchangeImplementations(
class_getInstanceMethod(self, #selector(getter: lineHeight))!,
class_getInstanceMethod(self, #selector(getter: swizzledLineHeight))!
)
}
private var isHiragino: Bool {
fontName.contains("Hiragino")
}
@objc private var swizzledAscender: CGFloat {
if isHiragino {
return self.swizzledAscender * 1.15
} else {
return self.swizzledAscender
}
}
@objc private var swizzledLineHeight: CGFloat {
if isHiragino {
return self.swizzledLineHeight * 1.25
} else {
return self.swizzledLineHeight
}
}
}
例如,在UIFont.swizzle()
中呼叫一次application(_:didFinishLaunchingWithOptions:)
。