现在的位置: 首页 > 综合 > 正文

CoreText入门

2018年05月12日 ⁄ 综合 ⁄ 共 16674字 ⁄ 字号 评论关闭

学习了网上的一些CoreText知识之后,总结了一下学习成果,自定义了一个Label控件。

Label特点:

1、可以设置文本中某些字段为关键字;

2、可以设置文本颜色和其中关键字的颜色;

3、可以设置文本下划线样式和其中关键字下划线样式;

4、可以指定文本字体与大小和其中关键字的字体与大小;

5、可以响应关键字点击;

说明一下其中的关键类的意义:

CHLabel.h 自定义的控件,继承自UILabel;

TestViewController.h 是项目的根视图控制器,其中使用了CHLabel;

下面看代码:

CHLabel 代码实现:

  1. #import <UIKit/UIKit.h>  
  2. #import<CoreText/CoreText.h>  
  3.   
  4. typedef enum  
  5. {  
  6.     kCHLabelUnderlineStyleNone = 0 ,  
  7.     kCHLabelUnderlineStyleSingle ,  
  8.     kCHLabelUnderlineStyleThick ,  
  9.     kCHLabelUnderlineStyleDouble   
  10. } CHLabelUnderlineStyle;  
  11.   
  12. @protocol CHLabelDelegate;  
  13. @interface CHLabel : UILabel  
  14. {  
  15.     NSString                  *_textCH;              //文本  
  16.     UIColor                   *_textColorCH;         //文本颜色  
  17.     UIFont                    *_textFontCH;          //文本字体  
  18.     CHLabelUnderlineStyle      _textUnderlineStyle;  //文本下划线  
  19.       
  20.     NSString                  *_textKeyWordCH;       //关键字  
  21.     UIColor                   *_textKeyWordColorCH;  //关键字颜色  
  22.     UIFont                    *_keyWordFontCH;       //关键字字体  
  23.     CHLabelUnderlineStyle      _keyWordUnderlineStyle;//关键字下划线  
  24.       
  25.     NSMutableArray            *_keyWordsCH;          //关键字数组  
  26.     NSMutableAttributedString *_attributedString;    //属性字符串  
  27. }  
  28.   
  29. @property (nonatomic,   copy) NSString                  *textCH;  
  30. @property (nonatomic, retain) UIColor                   *textColorCH;  
  31. @property (nonatomic,   copy) NSString                  *textKeyWordCH;  
  32. @property (nonatomic, retain) UIColor                   *textKeyWordColorCH;  
  33. @property (nonatomic, retain) UIFont                    *textFontCH;  
  34. @property (nonatomic, retain) UIFont                    *keyWordFontCH;   
  35. @property (nonatomic, retain) NSMutableArray            *keyWordsCH;  
  36. @property (nonatomic, retain) NSMutableAttributedString *attributedString;  
  37. @property (nonatomic, retain) id<CHLabelDelegate>        delegate;  
  38.   
  39. - (void) setText:(NSString *) textString andKeyWord:(NSString *) keyWord;  
  40.   
  41. - (void) setTextColor:(UIColor *)textColor andKeyWordColor:(UIColor *) keyWordColor;  
  42.   
  43. - (void) setTextFont: (UIFont *)textFont andKeyWordFont:(UIFont *) keyWordFont;  
  44.   
  45. - (void) setTextUnderlineStyle: (CHLabelUnderlineStyle)textUnderlineStyle andKeyWordUnderlineStyle:(CHLabelUnderlineStyle) keyWordUnderlineStyle;  
  46.   
  47. @end  
  48.   
  49. @protocol CHLabelDelegate <NSObject>  
  50. @optional  
  51. - (void) CHLabel:(CHLabel *) chLabel tapOnKeyWord:(NSString *) keyWord;  
  52.   
  53. @end  
  54. #import "CHLabel.h"  
  55.   
  56. @implementation CHLabel  
  57.   
  58. @synthesize textCH               = _textCH;  
  59. @synthesize textColorCH          = _textColorCH;  
  60. @synthesize textKeyWordCH        = _textKeyWordCH;  
  61. @synthesize textKeyWordColorCH   = _textKeyWordColorCH;  
  62. @synthesize textFontCH           = _textFontCH;  
  63. @synthesize keyWordFontCH        = _keyWordFontCH;  
  64. @synthesize keyWordsCH           = _keyWordsCH;  
  65. @synthesize attributedString     = _attributedString;  
  66. @synthesize delegate;  
  67.   
  68. void safeRelease(id pointer)  
  69. {  
  70.     if (!pointer)  
  71.     {  
  72.         [pointer release];  
  73.         pointer = nil;  
  74.     }  
  75. }  
  76.   
  77. - (void) dealloc  
  78. {  
  79.     safeRelease(_textCH);  
  80.     safeRelease(_textColorCH);  
  81.     safeRelease(_textKeyWordCH);  
  82.     safeRelease(_textKeyWordColorCH);  
  83.     safeRelease(_textFontCH);  
  84.     safeRelease(_keyWordFontCH);  
  85.     safeRelease(_keyWordsCH);  
  86.     safeRelease(_attributedString);  
  87.     safeRelease(delegate);  
  88.       
  89.     [super dealloc];  
  90. }  
  91.   
  92. - (void) initializtion  
  93. {  
  94.     _textKeyWordCH = nil;  
  95.     _textKeyWordColorCH = nil;  
  96.     _keyWordsCH = [[NSMutableArray alloc] init];  
  97. }  
  98.   
  99. - (id) init  
  100. {  
  101.     if (self = [super init])  
  102.     {  
  103.         [self initializtion];  
  104.     }  
  105.     return self;  
  106. }  
  107.   
  108. - (id)initWithFrame:(CGRect)frame  
  109. {  
  110.     if ([super initWithFrame:frame])  
  111.     {  
  112.         [self initializtion];  
  113.     }  
  114.     return self;  
  115. }  
  116.   
  117. - (void) setText:(NSString *) textString andKeyWord:(NSString *) keyWord  
  118. {  
  119.     if (self.text != textString)  
  120.     {  
  121.         self.text = textString;  
  122.         self.textCH = textString;  
  123.     }  
  124.       
  125.     [self fetchKeywordRange:keyWord];  
  126. }  
  127.   
  128. - (void) setTextColor:(UIColor *)textColor andKeyWordColor:(UIColor *) keyWordColor  
  129. {  
  130.     self.textColorCH = textColor;  
  131.     self.textKeyWordColorCH = keyWordColor;  
  132. }  
  133.   
  134. - (void) setTextFont:(UIFont *)textFont andKeyWordFont:(UIFont *) keyWordFont  
  135. {  
  136.     self.textFontCH = textFont;  
  137.     self.keyWordFontCH = keyWordFont;  
  138. }  
  139.   
  140. - (void) setTextUnderlineStyle: (CHLabelUnderlineStyle)textUnderlineStyle andKeyWordUnderlineStyle:(CHLabelUnderlineStyle) keyWordUnderlineStyle  
  141. {  
  142.     _textUnderlineStyle = textUnderlineStyle;  
  143.     _keyWordUnderlineStyle = keyWordUnderlineStyle;  
  144. }  
  145.   
  146. - (void) fetchKeywordRange:(NSString *)keyWord  
  147. {  
  148.     if (nil == keyWord) {  
  149.         return;  
  150.     }  
  151.       
  152.     NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:self.text];  
  153.     NSUInteger count = 0, length = [mutableAttributedString length];  
  154.     NSRange range = NSMakeRange(0, length);  
  155.       
  156.     count = 0, length = [mutableAttributedString length];  
  157.     range = NSMakeRange(0, length);  
  158.       
  159.     while(range.location != NSNotFound)  
  160.     {  
  161.         range = [[mutableAttributedString string] rangeOfString:keyWord options:0 range:range];  
  162.         if(range.location != NSNotFound) {  
  163.          
  164.             NSValue *value = [NSValue valueWithRange:range];  
  165.             if (range.length > 0) {  
  166.                 [self.keyWordsCH addObject:value];  
  167.             }  
  168.               
  169.             range = NSMakeRange(range.location + range.length, length - (range.location + range.length));  
  170.             count++;  
  171.         }  
  172.     }  
  173. }  
  174.   
  175. - (int) labelUnderlineType:(CHLabelUnderlineStyle) lType  
  176. {  
  177.     int underLineType;  
  178.     switch (lType) {  
  179.         case 0:  
  180.             underLineType = kCTUnderlineStyleNone;  
  181.             break;  
  182.         case 1:  
  183.             underLineType = kCTUnderlineStyleSingle;  
  184.             break;  
  185.         case 2:  
  186.             underLineType = kCTUnderlineStyleThick;  
  187.             break;  
  188.         case 3:  
  189.             underLineType = kCTUnderlineStyleDouble;  
  190.             break;  
  191.         default:  
  192.             underLineType = kCTUnderlineStyleNone;  
  193.             break;  
  194.     }  
  195.       
  196.     return underLineType;  
  197. }  
  198.   
  199. - (NSAttributedString *) richString:(NSString *) textString  
  200. {  
  201.     int length = [textString length];  
  202.     if (self.attributedString) {  
  203.         self.attributedString = nil;  
  204.     }  
  205.    self.attributedString = [[NSMutableAttributedString alloc] initWithString:textString];  
  206.     [self.attributedString addAttribute:(NSString *)(kCTForegroundColorAttributeName)  
  207.                              value:(id)self.textColorCH.CGColor  
  208.                              range:NSMakeRange(0, length)];  
  209.       
  210.     int numType = 0;  
  211.     CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberIntType, &numType);  
  212.     [self.attributedString addAttribute:(NSString *)kCTLigatureAttributeName  
  213.                                   value:(id)cfNum  
  214.                                   range:NSMakeRange(0, length)];  
  215.       
  216.     float fNum =3.0;  
  217.     CFNumberRef cfNum2 = CFNumberCreate(NULL, kCFNumberFloatType, &fNum);  
  218.     [self.attributedString addAttribute:(NSString *)(kCTStrokeColorAttributeName)  
  219.                                   value:(id)cfNum2  
  220.                                   range:NSMakeRange(0, length)];  
  221.       
  222.     if (!self.textFontCH) {  
  223.         self.textFontCH = self.font;  
  224.     }  
  225.     CTFontRef ctFont = CTFontCreateWithName((CFStringRef)self.textFontCH.fontName, self.textFontCH.pointSize, NULL);  
  226.     [self.attributedString addAttribute:(NSString *)(kCTFontAttributeName)  
  227.                                   value:(id)ctFont  
  228.                                   range:NSMakeRange(0, length)];  
  229.       
  230.     int underLineType = [self labelUnderlineType:_textUnderlineStyle];  
  231.     CFNumberRef cfUnderLine = CFNumberCreate(NULL, kCTUnderlineStyleThick, &underLineType);  
  232.     [self.attributedString addAttribute:(NSString *)(kCTUnderlineStyleAttributeName)  
  233.                                   value:(id)cfUnderLine  
  234.                                   range:NSMakeRange(0, length)];  
  235.       
  236.     if (self.textKeyWordColorCH != nil)  
  237.     {  
  238.         for (NSValue *value in self.keyWordsCH)  
  239.         {  
  240.             NSRange keyRange = [value rangeValue];  
  241.             [self.attributedString addAttribute:(NSString *)(kCTForegroundColorAttributeName)  
  242.                                           value:(id)self.textKeyWordColorCH.CGColor  
  243.                                           range:keyRange];  
  244.               
  245.             if (!self.keyWordFontCH) {  
  246.                 self.keyWordFontCH = self.font;  
  247.             }  
  248.             CTFontRef ctFont = CTFontCreateWithName((CFStringRef)self.keyWordFontCH.fontName, self.keyWordFontCH.pointSize, NULL);  
  249.             [self.attributedString addAttribute:(NSString *)(kCTFontAttributeName)  
  250.                                           value:(id)ctFont  
  251.                                           range:keyRange];  
  252.               
  253.             int underLineType = [self labelUnderlineType:_keyWordUnderlineStyle];  
  254.             CFNumberRef cfUnderLine = CFNumberCreate(NULL, kCTUnderlineStyleThick, &underLineType);  
  255.             [self.attributedString addAttribute:(NSString *)(kCTUnderlineStyleAttributeName)  
  256.                                           value:(id)cfUnderLine  
  257.                                           range:keyRange];  
  258.               
  259.             [self.attributedString addAttribute:@"option" value:[[self.attributedString string] substringWithRange:keyRange] range:keyRange];//弹出alert时候需要  
  260.         }  
  261.     }  
  262.       
  263.     return [[self.attributedString copy] autorelease];  
  264. }  
  265.   
  266. - (void) drawRect:(CGRect)rect  
  267. {  
  268.     CGContextRef context = UIGraphicsGetCurrentContext();  
  269.     CGContextSaveGState(context);  
  270.     CGContextConcatCTM(context, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, rect.size.height+6.5), 1.f, -1.f));  
  271.       
  272.     CGContextSetTextPosition(context, 0.0, 0.0);  
  273.     CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef) [self richString:self.text]);  
  274.       
  275. //    NSLog(@"AttributedString:%@", [self richString:self.text font:self.font]);  
  276.       
  277.     CGMutablePathRef leftColumnPath = CGPathCreateMutable();  
  278.     CGPathAddRect(leftColumnPath, NULL, rect);  
  279.     CTFrameRef leftFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), leftColumnPath, NULL);  
  280.     CTFrameDraw(leftFrame, context);  
  281.     CGContextRestoreGState(context);  
  282.     CGPathRelease(leftColumnPath);  
  283.     CFRelease(framesetter);  
  284. }  
  285.   
  286. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
  287.       
  288.     [super touchesEnded:touches withEvent:event];  
  289.       
  290.     CGPoint tapLocation = [[touches anyObject] locationInView:self];  
  291.     int total_height = [self getAttributedStringHeightWithString:self.attributedString WidthValue:self.frame.size.width];//width为自身宽度  
  292.     //判断点击是否超出范围  
  293.     if (tapLocation.y >= total_height) {  
  294.         return;  
  295.     }  
  296.       
  297.     /** 1. Setup CTFramesetter **/  
  298.     CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attributedString);  
  299.     /** 2. Create CTFrame **/  
  300.     CGMutablePathRef path = CGPathCreateMutable();  
  301.     CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width, 1000));//height越大越好,  
  302.       
  303.     CTFrameRef textFrameForKey = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);  
  304.     //[self drawFrame:textFrameForKey inContext:nil forString:nil];  
  305.     CFRelease (path);  
  306.     CFRelease (framesetter);  
  307.     //CTFrameGetLineOrigins  
  308.     NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrameForKey);  
  309.       
  310.     CGPoint origins[[linesArray count]];  
  311.     CTFrameGetLineOrigins(textFrameForKey, CFRangeMake(0, 0), origins);  
  312.     CFArrayRef lines = CTFrameGetLines(textFrameForKey);  
  313.       
  314.     CGFloat ascent;  
  315.     CGFloat descent;  
  316.     CGFloat leading;  
  317.       
  318.     CTLineRef line = (CTLineRef) [linesArray objectAtIndex:0];  
  319.     CTLineGetTypographicBounds(line, &ascent, &descent, &leading);  
  320.       
  321.     //CFIndex linesCount = CFArrayGetCount(lines);  
  322.       
  323.     int line_y = 1000- (int)origins[0].y;  //第一行line的原点y坐标  
  324.     int line_height = line_y + (int)descent +1; //每行的高度  
  325.       
  326.     int current_line = tapLocation.y/line_height;  
  327.       
  328.     CFIndex curentIndex = CTLineGetStringIndexForPosition((CTLineRef)CFArrayGetValueAtIndex(lines, current_line),tapLocation);  
  329.       
  330.     //判断超出范围  
  331.     if (curentIndex >[self.attributedString length]) {  
  332.         return;  
  333.     }  
  334.       
  335.     NSRange currentRange = NSMakeRange(0, [self.attributedString length]);  
  336.     //curentIndex  
  337.     NSDictionary *dic = [self.attributedString attributesAtIndex:curentIndex-1 effectiveRange:¤tRange];  
  338.     id option = [dic valueForKey:@"option"];  
  339.       
  340.     if (option) {  
  341.        
  342.         if ([delegate respondsToSelector:@selector(CHLabel:tapOnKeyWord:)])  
  343.         {  
  344.             [delegate CHLabel:self tapOnKeyWord:(NSString *)[dic valueForKey:@"option"]];  
  345.         }  
  346.     }  
  347. }  
  348.   
  349. //获取coretext高度  
  350. - (int)getAttributedStringHeightWithString:(NSAttributedString *)string  WidthValue:(int) width  
  351. {  
  352.     int total_height = 0;  
  353.       
  354.     //string 为要计算高度的NSAttributedString  
  355.     CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);  
  356.       
  357.     CGRect drawingRect = CGRectMake(0, 0, width, 1000);  //这里的高要设置足够大  
  358.     CGMutablePathRef path = CGPathCreateMutable();  
  359.     CGPathAddRect(path, NULL, drawingRect);  
  360.     CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);  
  361.     CGPathRelease(path);  
  362.     CFRelease(framesetter);  
  363.       
  364.     NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrame);  
  365.       
  366.     CGPoint origins[[linesArray count]];  
  367.     CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins);  
  368.       
  369.     int line_y = (int) origins[[linesArray count] -1].y;  //最后一行line的原点y坐标  
  370.       
  371.     CGFloat ascent;  
  372.     CGFloat descent;  
  373.     CGFloat leading;  
  374.       
  375.     CTLineRef line = (CTLineRef) [linesArray objectAtIndex:[linesArray count]-1];  
  376.     CTLineGetTypographicBounds(line, &ascent, &descent, &leading);  
  377.       
  378.     total_height = 1000 - line_y + (int) descent +1;    //+1为了纠正descent转换成int小数点后舍去的值  
  379.       
  380.     CFRelease(textFrame);  
  381.       
  382.     return total_height;  
  383. }  
  384.   
  385. @end  
  386.   
  387.   
  388. TestViewController.h 代码实现:  
  389. @interface TestViewController : UIViewController <CHLabelDelegate>  
  390. {  
  391.     IBOutlet UITextField *textString;  
  392.     IBOutlet UITextField *keyString;  
  393. }  
  394.   
  395. - (IBAction) showText:(id)sender;  
  396.   
  397. @end  
  398.   
  399. #import "TestViewController.h"  
  400.   
  401. @interface TestViewController ()  
  402.   
  403. @end  
  404.   
  405. @implementation TestViewController  
  406.   
  407. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil  
  408. {  
  409.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];  
  410.     if (self) {  
  411.         // Custom initialization  
  412.     }  
  413.     return self;  
  414. }  
  415.   
  416. - (IBAction) showText:(id)sender  
  417. {  
  418.     [textString resignFirstResponder];  
  419.     [keyString resignFirstResponder];  
  420.       
  421.     CHLabel *label = [[CHLabel alloc] initWithFrame:CGRectMake(10, 260, 300, 200)];  
  422.       
  423.     [label setUserInteractionEnabled:YES];  
  424.     [label setText:textString.text andKeyWord:keyString.text];  
  425.     [label setTextColor:[UIColor redColor] andKeyWordColor:[UIColor blueColor]];  
  426.     [label setTextUnderlineStyle:kCHLabelUnderlineStyleSingle andKeyWordUnderlineStyle:kCHLabelUnderlineStyleDouble];  
  427.     [label setTextFont:[UIFont systemFontOfSize:20] andKeyWordFont:[UIFont boldSystemFontOfSize:30]];  
  428.     label.backgroundColor = [UIColor lightGrayColor];  
  429.     [label setNumberOfLines:0];  
  430.     label.delegate = self;  
  431.       
  432.       
  433.     NSArray *fontArray = [UIFont familyNames];  
  434.     NSString *fontName;  
  435.     if ([fontArray count]) {  
  436.         fontName = [fontArray objectAtIndex:0];  
  437.     }  
  438.     [label setFont:[UIFont fontWithName:fontName size:20]];  
  439.       
  440.     [self.view addSubview:label];  
  441. //    [label setNeedsDisplay];  
  442.     [label release];  
  443. }  
  444.   
  445. - (void)viewDidLoad  
  446. {  
  447.     [super viewDidLoad];  
  448. }  
  449.   
  450. - (void)didReceiveMemoryWarning  
  451. {  
  452.     [super didReceiveMemoryWarning];  
  453. }  
  454.   
  455. #pragma mark CHLabelDelegate  
  456. - (void) CHLabel:(CHLabel *) chLabel tapOnKeyWord:(NSString *) keyWord  
  457. {  
  458.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"notice"  
  459.                                                     message:[NSString stringWithFormat:@"Tap on keyWord:%@", keyWord]  
  460.                                                    delegate:nil  
  461.                                           cancelButtonTitle:@"OK"  
  462.                                           otherButtonTitles:nil];  
  463.     [alert show];  
  464.     [alert release];  

}

完整的项目链接:http://pan.baidu.com/share/link?shareid=362100&uk=3674861929

转载请保留,原文链接:http://blog.csdn.net/zfpp25_/article/details/8639215

若发现有不合适或错误之处,还请批评指正,不胜感激。

抱歉!评论已关闭.