我想制作一个应用程序以包含自定义字体以渲染文本,加载它,然后与标准的UIKit
元素(如UILabel
)一起使用。这是否可行?
我想制作一个应用程序以包含自定义字体以渲染文本,加载它,然后与标准的UIKit
元素(如UILabel
)一起使用。这是否可行?
自定义字体支持
希望使用自定义字体的应用程序现在可以将这些字体包含在其应用程序包中,并通过在其Info.plist文件中包含UIAppFonts键来向系统注册这些字体。此键的值是一个字符串数组,用于标识应用程序包中的字体文件。当系统看到该键时,它会加载指定的字体并使其可用于应用程序。
一旦在Info.plist
中设置了字体,您可以像其他字体一样在IB或程序中使用自定义字体。
Apple Developer论坛上有一个正在进行的主题:
https://devforums.apple.com/thread/37824 (需要登录)
这里还有一个成果显著的简单三步教程(已删除损坏的链接)
Info.plist
文件中添加一个名为UIAppFonts
的键。UIAppFonts
数组中的项目输入Info.plist
[UIFont fontWithName:@"CustomFontName" size:12]
即可获取自定义字体,并将其与您的 UILabels 和 UITextViews 等一起使用。还要确保字体在您的复制束资源中。
for (NSString *familyName in [UIFont familyNames]) {
NSLog(@"Family %@", familyName);
NSLog(@"Names = %@", [UIFont fontNamesForFamilyName:familyName]);
}
- Steve Potter编辑:自iOS 3.2起,此功能已内置。如果需要支持3.2之前的版本,仍然可以使用此解决方案。
我创建了一个简单的模块,扩展了UILabel
并处理加载.ttf文件的操作。我在Apache许可证下发布了它,并将其放在了Github上这里。
重要的文件是FontLabel.h
和FontLabel.m
。
它使用了来自Genericrich's答案的一些代码。
在这里浏览源代码。
或者
将字体文件复制到资源中
为您的Info.plist
文件添加一个键,叫做UIAppFonts。 (“应用程序提供的字体”)
将此键设置为数组
对于每种字体,将字体文件的完整名称(包括扩展名)输入UIAppFonts数组项
保存Info.plist
现在,在您的应用程序中,只需调用[UIFont fontWithName:@"CustomFontName" size:15]
即可获得自定义字体,以与您的UILabels
和UITextViews
等一起使用。
在中使用自定义字体有一个简单的方法:
Chalkduster.ttf
)添加到XCode项目的资源文件夹中。info.plist
,添加一个名为UIAppFonts
的新键。此键的类型应为数组。Chalkduster.ttf
)添加到此数组中。[UIFont fontWithName:@"Chalkduster" size:16]
。不幸的是,IB不允许使用自定义字体初始化标签。请参见此问题以解决此问题。我最喜欢的解决方案是使用自定义UILabel
子类:
@implementation CustomFontLabel
- (id)initWithCoder:(NSCoder *)decoder
{
if (self = [super initWithCoder: decoder])
{
[self setFont: [UIFont fontWithName: @"Chalkduster" size: self.font.pointSize]];
}
return self;
}
@end
在 Info.plist 文件中添加条目“Fonts provided by application”,并将字体名称以字符串形式包含其中:
Fonts provided by application
Item 0 myfontname.ttf
Item 1 myfontname-bold.ttf
...
然后确认你的字体是否已经包含,可以运行以下命令:
for (NSString *familyName in [UIFont familyNames]) {
for (NSString *fontName in [UIFont fontNamesForFamilyName:familyName]) {
NSLog(@"%@", fontName);
}
}
请注意,您的ttf文件名可能与您在为标签设置字体时使用的名称不同(您可以使用上面的代码获取"fontWithName"参数):[label setFont:[UIFont fontWithName:@"MyFontName-Regular" size:18]];
编辑:自iOS3.2起,此答案已过时,请使用UIAppFonts。
我成功加载自定义UIFont
的唯一方法是通过私有的GraphicsServices框架。
下面的代码将加载应用程序主包中所有的.ttf
字体:
BOOL GSFontAddFromFile(const char * path);
NSUInteger loadFonts()
{
NSUInteger newFontCount = 0;
for (NSString *fontFile in [[NSBundle mainBundle] pathsForResourcesOfType:@"ttf" inDirectory:nil])
newFontCount += GSFontAddFromFile([fontFile UTF8String]);
return newFontCount;
}
一旦字体被加载,它们可以像苹果提供的字体一样使用:
NSLog(@"Available Font Families: %@", [UIFont familyNames]);
[label setFont:[UIFont fontWithName:@"Consolas" size:20.0f]];
如果API将来消失,甚至可以在运行时加载GraphicsServices:
#import <dlfcn.h>
NSUInteger loadFonts()
{
NSUInteger newFontCount = 0;
NSBundle *frameworkBundle = [NSBundle bundleWithIdentifier:@"com.apple.GraphicsServices"];
const char *frameworkPath = [[frameworkBundle executablePath] UTF8String];
if (frameworkPath) {
void *graphicsServices = dlopen(frameworkPath, RTLD_NOLOAD | RTLD_LAZY);
if (graphicsServices) {
BOOL (*GSFontAddFromFile)(const char *) = dlsym(graphicsServices, "GSFontAddFromFile");
if (GSFontAddFromFile)
for (NSString *fontFile in [[NSBundle mainBundle] pathsForResourcesOfType:@"ttf" inDirectory:nil])
newFontCount += GSFontAddFromFile([fontFile UTF8String]);
}
}
return newFontCount;
}
CGFontCreateWithDataProvider
。UIAppFonts
可用于3.2+。 - rpetrich[NSString sizeWithFont:[UIFont fontWithName:@"customFont" size:14]];
都会返回0宽度和高度。 - Luke Mcneice[UIFont fontWithName:@"fake name" size:22.0f]]
中使用了错误的字体名称。 - Eric Brotto使用 iOS 8
+ 和 Xcode 6
+ 您可以轻松完成此操作。以下是步骤:
1)将字体拖放到 Xcode
Supporting Files 文件夹中。不要忘记在添加到目标部分中标记您的应用程序。从此时起,您可以在 IB
中使用此字体,并从字体调色板中选择它。
2)要使此字体在设备上可用,请打开您的 info.plist
并添加 Fonts provided by application
键。它将包含 Item 0 键,您必须将字体名称添加为值。字体名称可能与字体文件名称不同。但首先,请尝试在大多数情况下添加您的文件名,这通常有效。
如果不行,这篇文章 总是帮助了我。
这里是来自该文章的 Swift 代码片段,以帮助您找到字体名称。
func allFonts(){
for family in UIFont.familyNames(){
println(family)
for name in UIFont.fontNamesForFamilyName(family.description)
{
println(" \(name)")
}
}
}
我想提醒一下,您需要将字体文件添加到您的目标构建阶段的复制包资源中。如果没有这样做,您将无法在设备上看到您的字体,并可能导致意外行为。
例如,当UITextField
有自定义字体,但此字体不在复制包资源中时,我遇到了一个bug
。当我转场到带有此textfield
的viewcontroller
时,会有大约4秒的延迟,直到viewDidLoad
函数被调用。解决字体问题后,此延迟被消除。因此,建议您仔细检查两次。(rdar://20028250)顺便说一句,我无法重现这个错误,但我确定问题出在字体上。
我是这样做的:
加载字体:
- (void)loadFont{
// Get the path to our custom font and create a data provider.
NSString *fontPath = [[NSBundle mainBundle] pathForResource:@"mycustomfont" ofType:@"ttf"];
CGDataProviderRef fontDataProvider = CGDataProviderCreateWithFilename([fontPath UTF8String]);
// Create the font with the data provider, then release the data provider.
customFont = CGFontCreateWithDataProvider(fontDataProvider);
CGDataProviderRelease(fontDataProvider);
}
现在,在您的 drawRect:
中,可以执行类似以下操作:
-(void)drawRect:(CGRect)rect{
[super drawRect:rect];
// Get the context.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
// Set the customFont to be the font used to draw.
CGContextSetFont(context, customFont);
// Set how the context draws the font, what color, how big.
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
CGContextSetFillColorWithColor(context, self.fontColor.CGColor);
UIColor * strokeColor = [UIColor blackColor];
CGContextSetStrokeColorWithColor(context, strokeColor.CGColor);
CGContextSetFontSize(context, 48.0f);
// Create an array of Glyph's the size of text that will be drawn.
CGGlyph textToPrint[[self.theText length]];
// Loop through the entire length of the text.
for (int i = 0; i < [self.theText length]; ++i) {
// Store each letter in a Glyph and subtract the MagicNumber to get appropriate value.
textToPrint[i] = [[self.theText uppercaseString] characterAtIndex:i] + 3 - 32;
}
CGAffineTransform textTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0);
CGContextSetTextMatrix(context, textTransform);
CGContextShowGlyphsAtPoint(context, 20, 50, textToPrint, [self.theText length]);
}
基本上,您需要通过文本进行一些暴力循环,并调整魔数来查找字体中的偏移量(这里,看到我使用了29),但它可以工作。
此外,您必须确保字体可以合法嵌入。 大多数字体都不行,并且有专门从事此类事情的律师,因此请注意。
CGContextShowTextAtPoint()
函数,尽管它不支持UTF-8编码。 - Ivan Vučica是的,您可以包含自定义字体。请参考UIFont文档中的fontWithName:size:
方法。
1) 确保将字体包含在资源文件夹中。
2) 字体的“名称”不一定是文件名。
3) 确保您有合法使用该字体的权利。通过将它包含在您的应用程序中,您也在分发该字体,因此您需要获得相应的使用权。
如果你正在使用 xcode 4.3
版本,则需要在 Copy Bundle Resources
中的 Build Phase
下添加字体,参考自 https://stackoverflow.com/users/1292829/arne 在线讨论中提供的解决方案:Custom Fonts Xcode 4.3。这对我有效,下面是我为实现应用程序自定义字体所采取的步骤:
OTF
(或 TTF
)文件拖放到新创建的组中,并接受 xcode 的选择,即将文件复制到项目文件夹中。UIAppFonts
数组,并将您的字体名称作为数组项列出。只写字体的名称,不包括后缀名(例如"GothamBold
","GothamBold-Italic
")。Project Navigator
上方的 project name
。Build Phases
选项卡。Copy Bundle Resources
"部分,然后单击 "+"
添加字体。添加到项目中
的每个字体,都要重复执行以上步骤。我建议您按照我的一个最喜欢的简短教程进行操作:http://codewithchris.com/common-mistakes-with-adding-custom-fonts-to-your-ios-app/,此信息来源于该教程。
步骤1 - 将.ttf或.otf文件从Finder拖到您的项目中
注意 - 确保在主应用程序目标上单击“添加到目标”框
如果您忘记点击添加到目标,则在项目层次结构中单击字体文件,在右侧面板中单击目标成员资格部分的主应用程序目标
确保您的字体是应用程序目标的一部分,请确保它们显示在Build Phases的Copy Bundle Resources中
步骤2 - 将字体文件名添加到您的Plist中
转到Info部分的Custom iOS Target Properties,并在该部分中的项目中添加一个名为Fonts provided by application
的键(您键入时应该会看到它作为选项出现,并且它将设置为一个数组。单击小箭头以打开数组项,并输入您要添加的.ttf或.otf文件的名称,以让您的应用程序知道这些是您希望可用的字体文件。
注意 - 如果此步骤后您的应用程序崩溃,请检查您在此处添加的项目的拼写
步骤3 - 找出字体名称,以便您可以调用它们
经常情况下,您的应用程序所看到的字体名称与您基于该字体文件名认为的不同,请将此代码放入您的代码中,并查看您的应用程序生成的日志,以查看要在代码中调用哪个字体名称
Swift
for family: String in UIFont.familyNames(){
print("\(family)")
for names: String in UIFont.fontNamesForFamilyName(family){
print("== \(names)")
}
}
Objective C
for (NSString* family in [UIFont familyNames]){
NSLog(@"%@", family);
for (NSString* name in [UIFont fontNamesForFamilyName: family]){
NSLog(@" %@", name);
}
}
你的日志应该长成这个样子:
第四步 - 使用从第三步中得到的名称使用您的新自定义字体
Swift
label.font = UIFont(name: "SourceSansPro-Regular", size: 18)
Objective C
label.font = [UIFont fontWithName:@"SourceSansPro-Regular" size:18];