从UIFontDescriptor创建UIFont时忽略UIFontWeightTrait和UIFontDescriptorFamilyAttribute

时间:2014-07-23 12:34:00

标签: ios7 uifont uifontdescriptor uifontweighttrait

鉴于以下代码和运行iOS 7.1或更高版本的设备:

 NSDictionary *fontTraitsDictionary = @{UIFontWeightTrait : @(-1.0)};
 NSDictionary *attributesDictionary = @{
                                       UIFontDescriptorFamilyAttribute : @"Helvetica Neue", 
                                       UIFontDescriptorTraitsAttribute : fontTraitsDictionary
                                       };
 UIFontDescriptor *ultraLightDescriptor = [UIFontDescriptor fontDescriptorWithFontAttributes:attributesDictionary];
 UIFont *shouldBeAnUltraLightFont = [UIFont fontWithDescriptor:ultraLightDescriptor size:24];

 NSLog(@"%@", shouldBeAnUltraLightFont);

我希望shouldBeAnUltraLightFont的值是HelveticaNeue-UltraLight的一个实例,但它是:

<UICTFont: 0x908d160> font-family: "Helvetica"; font-weight: normal; font-style: normal; font-size: 24.00pt

据我所知,我正在关注Apple文档。为什么完全忽略字体系列和字体粗细信息?

我尝试过的事情

  • 我尝试过其他家族名字,如Helvetica,Avenir等。
  • 我在valid range from -1 to 1中尝试了其他字体粗细,增量为0.25

无论这些变化如何,返回的字体在正常体重下始终是Helvetica的香草实例。

5 个答案:

答案 0 :(得分:12)

我遇到了同样的问题,文档没什么帮助。最后我发现使用family属性结合了face属性:

 UIFontDescriptor* desc = [UIFontDescriptor fontDescriptorWithFontAttributes:
        @{
            UIFontDescriptorFamilyAttribute: @"Helvetica Neue",
            UIFontDescriptorFaceAttribute: @"Light"
        }
    ];

答案 1 :(得分:6)

From the docs:

  

字体特征字典键

     

以下常量可用作从中检索有关字体描述符的信息的键   它的特质词典。

NSString *const UIFontSymbolicTrait;
NSString *const UIFontWeightTrait;
NSString *const UIFontWidthTrait;
NSString *const UIFontSlantTrait;

这对我来说就像这些密钥只是为从字体描述符获取信息而设计的 - 而不是设置它。例如,您可以这样做:

UIFont *font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
NSDictionary *traits = [font.fontDescriptor objectForKey:UIFontDescriptorTraitsAttribute];
CGFloat weight = [traits[UIFontWeightTrait] floatValue];

哪会告诉你你得到的字体比正常体重稍微重一点。这似乎没有那么有用,因为能够要求更轻的字体而不必给出确切的名称 - 但它似乎是预期的用途。

答案 2 :(得分:2)

在寻找粗体或斜体字体时,符号特征至少似乎得到尊重。所以这很好用:

+ (UIFont*)fontWithFamily:(NSString*)family bold:(BOOL)bold italic:(BOOL)italic size:(CGFloat)pointSize {
  UIFontDescriptorSymbolicTraits traits = 0;
  if (bold)   traits |= UIFontDescriptorTraitBold;
  if (italic) traits |= UIFontDescriptorTraitItalic;
  UIFontDescriptor* fd = [UIFontDescriptor
                          fontDescriptorWithFontAttributes:@{UIFontDescriptorFamilyAttribute: family,
                                                             UIFontDescriptorTraitsAttribute: @{UIFontSymbolicTrait:
                                                                                                  [NSNumber numberWithInteger:traits]}}];
  NSArray* matches = [fd matchingFontDescriptorsWithMandatoryKeys:
                      [NSSet setWithObjects:UIFontDescriptorFamilyAttribute, UIFontDescriptorTraitsAttribute, nil]];
  if (matches.count == 0) return nil;
  return [UIFont fontWithDescriptor:matches[0] size:pointSize];
}

e.g。 [MyClass fontWithFamily:@"Avenir Next Condensed" bold:YES italic:NO size:12.0f];

我认为这不会对OP有所帮助,OP正在寻找具有UIFontWeightTrait light 字体,但它可以帮助其他有类似问题的人。

答案 3 :(得分:0)

您可以使用CTFontDescriptorCreateCopyWithVariation,但是必须首先找到字体粗细的变化轴标识符。我已经使用以下方法在react-native-svg中实现了对可变字体粗细的支持:

- (CTFontRef)getGlyphFont
{
    NSString *fontFamily = topFont_->fontFamily;
    NSNumber *fontSize = [NSNumber numberWithDouble:topFont_->fontSize];

    NSString *fontWeight = RNSVGFontWeightStrings[topFont_->fontWeight];
    NSString *fontStyle = RNSVGFontStyleStrings[topFont_->fontStyle];

    BOOL fontFamilyFound = NO;
    NSArray *supportedFontFamilyNames = [UIFont familyNames];

    if ([supportedFontFamilyNames containsObject:fontFamily]) {
        fontFamilyFound = YES;
    } else {
        for (NSString *fontFamilyName in supportedFontFamilyNames) {
            if ([[UIFont fontNamesForFamilyName: fontFamilyName] containsObject:fontFamily]) {
                fontFamilyFound = YES;
                break;
            }
        }
    }
    fontFamily = fontFamilyFound ? fontFamily : nil;

    UIFont *font = [RCTFont updateFont:nil
                              withFamily:fontFamily
                                    size:fontSize
                                  weight:fontWeight
                                   style:fontStyle
                                 variant:nil
                         scaleMultiplier:1.0];

    CTFontRef ref = (__bridge CTFontRef)font;

    int weight = topFont_->absoluteFontWeight;
    if (weight == 400) {
        return ref;
    }

    CFArrayRef cgAxes = CTFontCopyVariationAxes(ref);
    CFIndex cgAxisCount = CFArrayGetCount(cgAxes);
    CFNumberRef wght_id = 0;

    for (CFIndex i = 0; i < cgAxisCount; ++i) {
        CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes, i);
        if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) {
            continue;
        }

        CFDictionaryRef cgAxisDict = (CFDictionaryRef)cgAxis;
        CFTypeRef axisName = CFDictionaryGetValue(cgAxisDict, kCTFontVariationAxisNameKey);
        CFTypeRef axisId = CFDictionaryGetValue(cgAxisDict, kCTFontVariationAxisIdentifierKey);

        if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) {
            continue;
        }
        CFStringRef axisNameString = (CFStringRef)axisName;
        NSString *axisNameNSString = (__bridge NSString *)(axisNameString);
        if (![@"Weight" isEqualToString:axisNameNSString]) {
            continue;
        }

        if (!axisId || CFGetTypeID(axisId) != CFNumberGetTypeID()) {
            continue;
        }
        wght_id = (CFNumberRef)axisId;
        break;
    }

    if (wght_id == 0) {
        return ref;
    }
    UIFontDescriptor *uifd = font.fontDescriptor;
    CTFontDescriptorRef ctfd = (__bridge CTFontDescriptorRef)(uifd);
    CTFontDescriptorRef newfd = CTFontDescriptorCreateCopyWithVariation(ctfd, wght_id, (CGFloat)weight);
    CTFontRef newfont = CTFontCreateCopyWithAttributes(ref, (CGFloat)[fontSize doubleValue], nil, newfd);
    return newfont;
} 

https://github.com/react-native-community/react-native-svg/blob/bf0adb4a8206065ecb9e7cdaa18c3140d24ae338/ios/Text/RNSVGGlyphContext.m#L137-L235

答案 4 :(得分:0)

这对我有用:

np.array(list(zip(df.x,df.y)))
Out[810]: 
array([[8, 7],
       [0, 2],
       [2, 2],
       [0, 4],
       [9, 2],
       [1, 3]])