2014-02-19 1 views
2

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 

지금이 배열을 통해 순차적 I 루프 텍스트 뷰의 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]; 
    }]; 
    } 

: 나는이 방법을 사용 난 횡단 범위 (예를 들어, NSMakeRange(9,28)NSMakeRange(26,7)) 밑줄의 두께는 항상 마지막 요소의 글꼴 크기의 종속 값을 갖는 두 개의 TextFormattingElement 인스턴스가있는 경우.

enter image description here

제 2 개 형식 요소의 매개 변수는 다음과 같습니다 :

1 : 위치 = 9, 길이 = 28, 글꼴 이름 = TimesNewRomanPSMT, fontSize는 =이의 그림이 스크린 샷에서 볼 수 있습니다 15 FONTCOLOR = UIDeviceRGBColorSpace 1 0 0 1 isBold = 0 isItalic = 0 isUnderlined = 1 isStriked = 0

2 : 위치 = 26, 길이 = 7, 폰트 명 = TimesNewRomanPSMT, fontSize는 = 25 FONTCOLOR = UIDeviceRGBColo 어떻게 내가 할 수있는

enter image description here

: rSpace 0 0 1 1, isBold = 1, isItalic = 0, isUnderlined = 1, isStriked = 0

하지만 구글 문서 도구와 같은 효과를 얻으려면 TextKit을 사용하여이 작업을 수행합니까?

답변

7

iOS 7에서는 의 하위 클래스로 원하는 것을 할 수 있습니다. -drawUnderlineForGlyphRange:underlineType:baselineOffset:lineFragmentRect:lineFragmentGlyphRange:containerOrigin: 텍스트 시스템 개체를 만드는 작은 샘플로 원하는 밑줄을 그립니다.

@implementation ViewController 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // setup text handling with our subclass of NSLayoutManager 
    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:@"Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do;"]; 

    MyLayoutManager *textLayout = [[MyLayoutManager alloc] init]; 

    [textStorage addLayoutManager:textLayout]; 

    NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size]; 

    [textLayout addTextContainer:textContainer]; 
    UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0,20,self.view.bounds.size.width,self.view.bounds.size.height-20) 
               textContainer:textContainer]; 
    [self.view addSubview:textView]; 

    // setup test attributes 
    UIFont *font = [UIFont fontWithName:@"TimesNewRomanPSMT" size:15]; 

    NSMutableDictionary *attributesToSetDict = [NSMutableDictionary dictionary]; 

    [attributesToSetDict setObject:font forKey:NSFontAttributeName]; 
    [attributesToSetDict setObject:[UIColor blueColor] forKey:NSForegroundColorAttributeName]; 
    [attributesToSetDict setObject:@1 forKey:NSUnderlineStyleAttributeName]; 

    [textView.textStorage setAttributes:attributesToSetDict range:NSMakeRange(9, 28)]; 

    UIFontDescriptor *fontDescriptor = [font fontDescriptor]; 
    attributesToSetDict = [NSMutableDictionary dictionary]; 
    [attributesToSetDict setObject:[UIFont fontWithDescriptor:fontDescriptor size:25] forKey:NSFontAttributeName]; 
    [attributesToSetDict setObject:[UIColor redColor] forKey:NSForegroundColorAttributeName]; 
    [attributesToSetDict setObject:@1 forKey:NSUnderlineStyleAttributeName]; 

    [textView.textStorage setAttributes:attributesToSetDict range:NSMakeRange(26, 7)]; 
} 
@end 

@implementation MyLayoutManager 
- (void)drawUnderlineForGlyphRange:(NSRange)glyphRange underlineType:(NSUnderlineStyle)underlineVal baselineOffset:(CGFloat)baselineOffset lineFragmentRect:(CGRect)lineRect lineFragmentGlyphRange:(NSRange)lineGlyphRange containerOrigin:(CGPoint)containerOrigin 
{ 
    /* For the sample we consider that underlineVal is equals to NSUnderlineStyleSingle */ 

    /* 
    * We need to create a CTFontRef as UIFont doesn't provided 'Underline Position' and 'Underline Thickness' 
    */ 

    // get current UIFont for the glyphRange 
    NSRange characterRange = [self characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; 
    UIFont *font = [[self.textStorage attributesAtIndex:characterRange.location effectiveRange:NULL] objectForKey:NSFontAttributeName]; 

    CTFontRef ctfont = CTFontCreateWithName((CFStringRef)[font fontName], [font pointSize], NULL); 

    CGPoint startLocation = [self locationForGlyphAtIndex:glyphRange.location]; 
    CGPoint endLocation = [self locationForGlyphAtIndex:NSMaxRange(glyphRange)]; 

    CGContextRef ctx = UIGraphicsGetCurrentContext(); 

    // -underlineGlyphRange:underlineType:lineFragmentRect:lineFragmentGlyphRange:containerOrigin: already set color and line width 
    // for the current context 

    // reset line width with current font underline thickness 
    CGContextSetLineWidth(ctx, CTFontGetUnderlineThickness(ctfont)); 

    CGContextMoveToPoint(ctx, startLocation.x + containerOrigin.x, startLocation.y + containerOrigin.y - CTFontGetUnderlinePosition(ctfont)); 
    CGContextAddLineToPoint(ctx, endLocation.x + containerOrigin.x, endLocation.y + containerOrigin.y - CTFontGetUnderlinePosition(ctfont)); 

    CGContextStrokePath(ctx); 

    CFRelease(ctfont); 
} 

sample

+0

감사합니다! 나는 또한이 방향으로 작업하기 시작했으나 밑줄 두께에 대한 수식을 찾고 문자에서 들여 쓰기에 밑줄을 긋는 데 문제가있었습니다. 이제 귀하의 답변으로 나는 핵심 텍스트로 그것을 어떻게하는지 압니다. 큰 당신에게 수천 번 감사드립니다 !!! – xexe

+0

@xexe 여러분을 환영합니다. – Emmanuel