下划线文本 - 具有不同字体大小的交叉范围中的线条粗细

时间:2014-02-19 11:28:54

标签: ios uitextview nsattributedstring textkit

我正在使用UITextView的textStorage属性。我有我的班级TextFormattingElement的字符串和数组。此类的一个实例由NSRange(此元素必须在文本中应用)和一些格式参数组成:

@interface TextFormattingElement : NSObject

@property (nonatomic) NSRange range;
@property (nonatomic, strong) NSString *fontName;   //e.g. @"TimesNewRomanPSMT"
@property (nonatomic) int fontSize;
@property (nonatomic, strong) UIColor *fontColor;
@property (nonatomic) BOOL isBold;
@property (nonatomic) BOOL isItalic;
@property (nonatomic) BOOL isUnderlined;
@property (nonatomic) BOOL isStriked;

@end

现在我循环遍历此数组并连续将此元素应用于textView的textStorage。我用这个方法:

-(void)setFontWithName:(NSString*)name AndSize:(float)fontSize AndTextColor:(UIColor*)textColor AndIsBold:(BOOL)isBold AndIsItalic:(BOOL)isItalic AndIsUnderlined:(BOOL)isUnderLined andIsStriked:(BOOL)isStriked ToRange:(NSRange)rangeToSet{
   __block UIFont *font = [UIFont fontWithName:name size:fontSize];
   __block UIFontDescriptor *fontDescriptor = [font fontDescriptor];

   [textView.textStorage enumerateAttributesInRange:rangeToSet options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
      NSParagraphStyle *paragraphStyle = [attrs objectForKey:NSParagraphStyleAttributeName];

      NSMutableDictionary *attributesToSetDict = [NSMutableDictionary dictionary];
     [attributesToSetDict setObject:paragraphStyle forKey:NSParagraphStyleAttributeName];  //i need to clear all attributes at this range exсept NSParagraphStyleAttributeName

      if(isBold){
          uint32_t existingTraitsWithNewTrait = [fontDescriptor symbolicTraits] | UIFontDescriptorTraitBold;
          fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:existingTraitsWithNewTrait];
      }

      if(isItalic){
          uint32_t existingTraitsWithNewTrait = [fontDescriptor symbolicTraits] | UIFontDescriptorTraitItalic;
          fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:existingTraitsWithNewTrait];
      }

      font = [UIFont fontWithDescriptor:fontDescriptor size:fontSize];
      [attributesToSetDict setObject:font forKey:NSFontAttributeName];
      [attributesToSetDict setObject:textColor forKey:NSForegroundColorAttributeName];

      if(isUnderLined){
          [attributesToSetDict setObject:@1 forKey:NSUnderlineStyleAttributeName];
      }

      if(isStriked){
          //TODO: isStriked
      }

      [textView.textStorage setAttributes:attributesToSetDict range:range];
    }];
  }

我有一个问题:如果我有两个带有交叉范围的TextFormattingElement个实例(例如NSMakeRange(9,28)NSMakeRange(26,7)),则下划线的粗细总是取决于最后一个元素的字体大小。你可以在这个截图中看到这个例子:

enter image description here

我的2个格式元素的参数是:

1st:location = 9,length = 28,fontName = TimesNewRomanPSMT,fontSize = 15,fontColor = UIDeviceRGBColorSpace 1 0 0 1,isBold = 0,isItalic = 0,isUnderlined = 1,isStriked = 0

第二名:位置= 26,长度= 7,fontName = TimesNewRomanPSMT,fontSize = 25,fontColor = UIDeviceRGBColorSpace 0 0 1 1,isBold = 1,isItalic = 0,isUnderlined = 1,isStriked = 0

但我想在Google文档中获得效果:

enter image description here

如何使用TextKit执行此操作?

1 个答案:

答案 0 :(得分:7)

在iOS 7上,您可以使用覆盖NSLayoutManager的{​​{1}}子类执行您想要的操作 一个创建文本系统对象的小样本,并绘制想要的下划线。

-drawUnderlineForGlyphRange:underlineType:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin:

sample