简体   繁体   中英

Bold `<b>` tag and Italic `<i>` tag not applied for custom font family

I got below html string with <b> and <i> tags.

inputString = @"<b> Sample bold text </b> Normal Text <i> sample italic </i>";

And below method will return attributed text for input html string.

+(NSAttributedString *) returnRichTextForString:(NSString *) inputString {

  NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:[inputString dataUsingEncoding:NSUTF8StringEncoding]  options:@{   
        NSDocumentTypeDocumentAttribute:  NSHTMLTextDocumentType,
        NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)
      }
  documentAttributes:nil
  error:nil];

   return attributedString;
}

Then custom font size, family and pass it into above method.

NSString * strigAfterFontWrapper =  [NSString stringWithFormat:@"<style type='text/css'> body {font-size: %fpx}</style><font face='%@'>%@</font>", fontSize , customFontFamily, inputString];

label.numberOfLines = 0;

NSAttributedString *attributedstring = [NTUtilities returnRichTextForString:strigAfterFontWrapper];

label.attributedText = attributedstring;

But, <b> and <i> are not applied on the label!

It works fine with default system font! Any clue why it fails in the case of custom fonts ? What should I include to get bold or italic ?

Solved this problem with my own hack. Before jumping to solution, I clarified effects of newly added custom fonts in iOS. That is, if that font family comes with ready made Bold / Italic etc attributes, it will cause above problem. If not, you will face such problems.

Solution :

In +(NSAttributedString *) returnRichTextForString:(NSString *) inputString method, added below lines to overwrite existing NSAttributedString attributes.

[attributedString beginEditing];

[attributedString enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
    if (value) {
        NSMutableParagraphStyle *myStyle = (NSMutableParagraphStyle *)value;
        //Hack for bold effect to custom fonts
        if (myStyle.minimumLineHeight == 101) {
            [myStyle setMinimumLineHeight:0];
            [attributedString addAttribute:NSStrokeWidthAttributeName
                                     value:[NSNumber numberWithFloat:-3.0] range:range];
        }
        //Hack for italic/skew effect to custom fonts
        if (myStyle.minimumLineHeight == 99) {
            [myStyle setMinimumLineHeight:0];
            [attributedString addAttribute:NSObliquenessAttributeName
                                     value:[NSNumber numberWithFloat:0.30] range:range];
        }

    }
}];

[attributedString endEditing];

Below updates for the markup in inputString

<style type='text/css'> b { line-height:101px;} i {line-height:99px;} </style>

Hence, final mark up after upending above lines,

inputString = @"<b> Sample bold text </b> Normal Text <i> sample italic </i><style type='text/css'> b { line-height:101px;} i {line-height:99px;} </style>";

Here,

Trick is to identify bold and italic tags based on line-height value in html and comparing it with minimumLineHeight attribute of paragraph style. ie for example if line-height 101 then it will be bold and 99 then consider it as italic.

UPDATE : This fails when and both are applied at the same text. To overcome this problem, Here I shared slightly modified logic. Keeping same logic to identify italic and for bold I added below lines before end editing attributes of NSAttributedstring ,

//Hack for bold effect.
[attributedString enumerateAttribute:NSStrikethroughStyleAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {

    if (value) {

        [attributedString addAttribute:NSStrokeWidthAttributeName
                                                 value:[NSNumber numberWithFloat:-3.0] range:range];

        [attributedString addAttribute:NSStrikethroughStyleAttributeName
                                 value:[NSNumber numberWithFloat:0.0] range:range];
    }

}];

and in html,

 b { text-decoration:line-through;}

My complete method is here below :

  +(NSAttributedString *) returnRichTextForString:(NSString *) inputString {

  NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:[inputString dataUsingEncoding:NSUTF8StringEncoding]  options:@{
                                                                                                                                                                 NSDocumentTypeDocumentAttribute:  NSHTMLTextDocumentType,
                                                                                                                                                                 NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)
                                                                                                                                                              }
                                                                           documentAttributes:nil
                                                                                        error:nil];


 [attributedString beginEditing];

   //Hack for italic/skew effect to custom fonts
 [attributedString enumerateAttribute:NSParagraphStyleAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {

    if (value) {

        NSMutableParagraphStyle *myStyle = (NSMutableParagraphStyle *)value;

        if (myStyle.minimumLineHeight == 99) {
            [myStyle setMinimumLineHeight:0];
            [attributedString addAttribute:NSObliquenessAttributeName
                                     value:[NSNumber numberWithFloat:0.30] range:range];
        }

    }
}];

     //Hack for bold effect.
 [attributedString enumerateAttribute:NSStrikethroughStyleAttributeName inRange:NSMakeRange(0, attributedString.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {

     if (value) {

        [attributedString addAttribute:NSStrokeWidthAttributeName
                                                 value:[NSNumber numberWithFloat:-3.0] range:range];

        [attributedString addAttribute:NSStrikethroughStyleAttributeName
                                 value:[NSNumber numberWithFloat:0.0] range:range];
      }

}];


[attributedString endEditing];

return attributedString;
}

You should try with System fonts just to rule out the possibility that your custom fonts are not added to the project properly.

I once had the same issue but with labels.

This answer solved it for me. Maybe this helps you.

Edit:

Found a very nice article on how to add custom fonts to iOS app

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM