textStorage의 속성으로 작업하고 UITextView
있습니다. 내 클래스의 개체의 문자열과 배열이 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)
) 가있는 두 인스턴스가 있는 경우 밑줄의 두께는 항상 마지막 요소의 글꼴 크기에 따라 달라지는 값을 갖습니다. 이 그림은이 스크린 샷에서 볼 수 있습니다.
내 두 가지 서식 지정 요소의 매개 변수는 다음과 같습니다.
첫 번째 : 위치 = 9, 길이 = 28, fontName = TimesNewRomanPSMT, fontSize = 15, fontColor = UIDeviceRGBColorSpace 10 0 1, isBold = 0, isItalic = 0, isUnderlined = 1, isStriked = 0
두 번째 : 위치 = 26, 길이 = 7, fontName = TimesNewRomanPSMT, fontSize = 25, fontColor = UIDeviceRGBColorSpace 012 1, isBold = 1, isItalic = 0, isUnderlined = 1, isStriked = 0
하지만 Google 문서에서와 같은 효과를 얻고 싶습니다.
TextKit을 사용하여 어떻게 할 수 있습니까?
iOS 7에서는 텍스트 시스템 개체를 만들고 원하는 밑줄을 그리는 작은 샘플 NSLayoutManager
재정 -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);
}
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다