学习了网上的一些CoreText知识之后,总结了一下学习成果,自定义了一个Label控件。
Label特点:
1、可以设置文本中某些字段为关键字;
2、可以设置文本颜色和其中关键字的颜色;
3、可以设置文本下划线样式和其中关键字下划线样式;
4、可以指定文本字体与大小和其中关键字的字体与大小;
5、可以响应关键字点击;
说明一下其中的关键类的意义:
CHLabel.h 自定义的控件,继承自UILabel;
TestViewController.h 是项目的根视图控制器,其中使用了CHLabel;
下面看代码:
CHLabel 代码实现:
- #import <UIKit/UIKit.h>
- #import<CoreText/CoreText.h>
- typedef enum
- {
- kCHLabelUnderlineStyleNone = 0 ,
- kCHLabelUnderlineStyleSingle ,
- kCHLabelUnderlineStyleThick ,
- kCHLabelUnderlineStyleDouble
- } CHLabelUnderlineStyle;
- @protocol CHLabelDelegate;
- @interface CHLabel : UILabel
- {
- NSString *_textCH; //文本
- UIColor *_textColorCH; //文本颜色
- UIFont *_textFontCH; //文本字体
- CHLabelUnderlineStyle _textUnderlineStyle; //文本下划线
- NSString *_textKeyWordCH; //关键字
- UIColor *_textKeyWordColorCH; //关键字颜色
- UIFont *_keyWordFontCH; //关键字字体
- CHLabelUnderlineStyle _keyWordUnderlineStyle;//关键字下划线
- NSMutableArray *_keyWordsCH; //关键字数组
- NSMutableAttributedString *_attributedString; //属性字符串
- }
- @property (nonatomic, copy) NSString *textCH;
- @property (nonatomic, retain) UIColor *textColorCH;
- @property (nonatomic, copy) NSString *textKeyWordCH;
- @property (nonatomic, retain) UIColor *textKeyWordColorCH;
- @property (nonatomic, retain) UIFont *textFontCH;
- @property (nonatomic, retain) UIFont *keyWordFontCH;
- @property (nonatomic, retain) NSMutableArray *keyWordsCH;
- @property (nonatomic, retain) NSMutableAttributedString *attributedString;
- @property (nonatomic, retain) id<CHLabelDelegate> delegate;
- - (void) setText:(NSString *) textString andKeyWord:(NSString *) keyWord;
- - (void) setTextColor:(UIColor *)textColor andKeyWordColor:(UIColor *) keyWordColor;
- - (void) setTextFont: (UIFont *)textFont andKeyWordFont:(UIFont *) keyWordFont;
- - (void) setTextUnderlineStyle: (CHLabelUnderlineStyle)textUnderlineStyle andKeyWordUnderlineStyle:(CHLabelUnderlineStyle) keyWordUnderlineStyle;
- @end
- @protocol CHLabelDelegate <NSObject>
- @optional
- - (void) CHLabel:(CHLabel *) chLabel tapOnKeyWord:(NSString *) keyWord;
- @end
- #import "CHLabel.h"
- @implementation CHLabel
- @synthesize textCH = _textCH;
- @synthesize textColorCH = _textColorCH;
- @synthesize textKeyWordCH = _textKeyWordCH;
- @synthesize textKeyWordColorCH = _textKeyWordColorCH;
- @synthesize textFontCH = _textFontCH;
- @synthesize keyWordFontCH = _keyWordFontCH;
- @synthesize keyWordsCH = _keyWordsCH;
- @synthesize attributedString = _attributedString;
- @synthesize delegate;
- void safeRelease(id pointer)
- {
- if (!pointer)
- {
- [pointer release];
- pointer = nil;
- }
- }
- - (void) dealloc
- {
- safeRelease(_textCH);
- safeRelease(_textColorCH);
- safeRelease(_textKeyWordCH);
- safeRelease(_textKeyWordColorCH);
- safeRelease(_textFontCH);
- safeRelease(_keyWordFontCH);
- safeRelease(_keyWordsCH);
- safeRelease(_attributedString);
- safeRelease(delegate);
- [super dealloc];
- }
- - (void) initializtion
- {
- _textKeyWordCH = nil;
- _textKeyWordColorCH = nil;
- _keyWordsCH = [[NSMutableArray alloc] init];
- }
- - (id) init
- {
- if (self = [super init])
- {
- [self initializtion];
- }
- return self;
- }
- - (id)initWithFrame:(CGRect)frame
- {
- if ([super initWithFrame:frame])
- {
- [self initializtion];
- }
- return self;
- }
- - (void) setText:(NSString *) textString andKeyWord:(NSString *) keyWord
- {
- if (self.text != textString)
- {
- self.text = textString;
- self.textCH = textString;
- }
- [self fetchKeywordRange:keyWord];
- }
- - (void) setTextColor:(UIColor *)textColor andKeyWordColor:(UIColor *) keyWordColor
- {
- self.textColorCH = textColor;
- self.textKeyWordColorCH = keyWordColor;
- }
- - (void) setTextFont:(UIFont *)textFont andKeyWordFont:(UIFont *) keyWordFont
- {
- self.textFontCH = textFont;
- self.keyWordFontCH = keyWordFont;
- }
- - (void) setTextUnderlineStyle: (CHLabelUnderlineStyle)textUnderlineStyle andKeyWordUnderlineStyle:(CHLabelUnderlineStyle) keyWordUnderlineStyle
- {
- _textUnderlineStyle = textUnderlineStyle;
- _keyWordUnderlineStyle = keyWordUnderlineStyle;
- }
- - (void) fetchKeywordRange:(NSString *)keyWord
- {
- if (nil == keyWord) {
- return;
- }
- NSMutableAttributedString *mutableAttributedString = [[NSMutableAttributedString alloc] initWithString:self.text];
- NSUInteger count = 0, length = [mutableAttributedString length];
- NSRange range = NSMakeRange(0, length);
- count = 0, length = [mutableAttributedString length];
- range = NSMakeRange(0, length);
- while(range.location != NSNotFound)
- {
- range = [[mutableAttributedString string] rangeOfString:keyWord options:0 range:range];
- if(range.location != NSNotFound) {
- NSValue *value = [NSValue valueWithRange:range];
- if (range.length > 0) {
- [self.keyWordsCH addObject:value];
- }
- range = NSMakeRange(range.location + range.length, length - (range.location + range.length));
- count++;
- }
- }
- }
- - (int) labelUnderlineType:(CHLabelUnderlineStyle) lType
- {
- int underLineType;
- switch (lType) {
- case 0:
- underLineType = kCTUnderlineStyleNone;
- break;
- case 1:
- underLineType = kCTUnderlineStyleSingle;
- break;
- case 2:
- underLineType = kCTUnderlineStyleThick;
- break;
- case 3:
- underLineType = kCTUnderlineStyleDouble;
- break;
- default:
- underLineType = kCTUnderlineStyleNone;
- break;
- }
- return underLineType;
- }
- - (NSAttributedString *) richString:(NSString *) textString
- {
- int length = [textString length];
- if (self.attributedString) {
- self.attributedString = nil;
- }
- self.attributedString = [[NSMutableAttributedString alloc] initWithString:textString];
- [self.attributedString addAttribute:(NSString *)(kCTForegroundColorAttributeName)
- value:(id)self.textColorCH.CGColor
- range:NSMakeRange(0, length)];
- int numType = 0;
- CFNumberRef cfNum = CFNumberCreate(NULL, kCFNumberIntType, &numType);
- [self.attributedString addAttribute:(NSString *)kCTLigatureAttributeName
- value:(id)cfNum
- range:NSMakeRange(0, length)];
- float fNum =3.0;
- CFNumberRef cfNum2 = CFNumberCreate(NULL, kCFNumberFloatType, &fNum);
- [self.attributedString addAttribute:(NSString *)(kCTStrokeColorAttributeName)
- value:(id)cfNum2
- range:NSMakeRange(0, length)];
- if (!self.textFontCH) {
- self.textFontCH = self.font;
- }
- CTFontRef ctFont = CTFontCreateWithName((CFStringRef)self.textFontCH.fontName, self.textFontCH.pointSize, NULL);
- [self.attributedString addAttribute:(NSString *)(kCTFontAttributeName)
- value:(id)ctFont
- range:NSMakeRange(0, length)];
- int underLineType = [self labelUnderlineType:_textUnderlineStyle];
- CFNumberRef cfUnderLine = CFNumberCreate(NULL, kCTUnderlineStyleThick, &underLineType);
- [self.attributedString addAttribute:(NSString *)(kCTUnderlineStyleAttributeName)
- value:(id)cfUnderLine
- range:NSMakeRange(0, length)];
- if (self.textKeyWordColorCH != nil)
- {
- for (NSValue *value in self.keyWordsCH)
- {
- NSRange keyRange = [value rangeValue];
- [self.attributedString addAttribute:(NSString *)(kCTForegroundColorAttributeName)
- value:(id)self.textKeyWordColorCH.CGColor
- range:keyRange];
- if (!self.keyWordFontCH) {
- self.keyWordFontCH = self.font;
- }
- CTFontRef ctFont = CTFontCreateWithName((CFStringRef)self.keyWordFontCH.fontName, self.keyWordFontCH.pointSize, NULL);
- [self.attributedString addAttribute:(NSString *)(kCTFontAttributeName)
- value:(id)ctFont
- range:keyRange];
- int underLineType = [self labelUnderlineType:_keyWordUnderlineStyle];
- CFNumberRef cfUnderLine = CFNumberCreate(NULL, kCTUnderlineStyleThick, &underLineType);
- [self.attributedString addAttribute:(NSString *)(kCTUnderlineStyleAttributeName)
- value:(id)cfUnderLine
- range:keyRange];
- [self.attributedString addAttribute:@"option" value:[[self.attributedString string] substringWithRange:keyRange] range:keyRange];//弹出alert时候需要
- }
- }
- return [[self.attributedString copy] autorelease];
- }
- - (void) drawRect:(CGRect)rect
- {
- CGContextRef context = UIGraphicsGetCurrentContext();
- CGContextSaveGState(context);
- CGContextConcatCTM(context, CGAffineTransformScale(CGAffineTransformMakeTranslation(0, rect.size.height+6.5), 1.f, -1.f));
- CGContextSetTextPosition(context, 0.0, 0.0);
- CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef) [self richString:self.text]);
- // NSLog(@"AttributedString:%@", [self richString:self.text font:self.font]);
- CGMutablePathRef leftColumnPath = CGPathCreateMutable();
- CGPathAddRect(leftColumnPath, NULL, rect);
- CTFrameRef leftFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), leftColumnPath, NULL);
- CTFrameDraw(leftFrame, context);
- CGContextRestoreGState(context);
- CGPathRelease(leftColumnPath);
- CFRelease(framesetter);
- }
- - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
- [super touchesEnded:touches withEvent:event];
- CGPoint tapLocation = [[touches anyObject] locationInView:self];
- int total_height = [self getAttributedStringHeightWithString:self.attributedString WidthValue:self.frame.size.width];//width为自身宽度
- //判断点击是否超出范围
- if (tapLocation.y >= total_height) {
- return;
- }
- /** 1. Setup CTFramesetter **/
- CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)self.attributedString);
- /** 2. Create CTFrame **/
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddRect(path, NULL, CGRectMake(0, 0, self.frame.size.width, 1000));//height越大越好,
- CTFrameRef textFrameForKey = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
- //[self drawFrame:textFrameForKey inContext:nil forString:nil];
- CFRelease (path);
- CFRelease (framesetter);
- //CTFrameGetLineOrigins
- NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrameForKey);
- CGPoint origins[[linesArray count]];
- CTFrameGetLineOrigins(textFrameForKey, CFRangeMake(0, 0), origins);
- CFArrayRef lines = CTFrameGetLines(textFrameForKey);
- CGFloat ascent;
- CGFloat descent;
- CGFloat leading;
- CTLineRef line = (CTLineRef) [linesArray objectAtIndex:0];
- CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
- //CFIndex linesCount = CFArrayGetCount(lines);
- int line_y = 1000- (int)origins[0].y; //第一行line的原点y坐标
- int line_height = line_y + (int)descent +1; //每行的高度
- int current_line = tapLocation.y/line_height;
- CFIndex curentIndex = CTLineGetStringIndexForPosition((CTLineRef)CFArrayGetValueAtIndex(lines, current_line),tapLocation);
- //判断超出范围
- if (curentIndex >[self.attributedString length]) {
- return;
- }
- NSRange currentRange = NSMakeRange(0, [self.attributedString length]);
- //curentIndex
- NSDictionary *dic = [self.attributedString attributesAtIndex:curentIndex-1 effectiveRange:¤tRange];
- id option = [dic valueForKey:@"option"];
- if (option) {
- if ([delegate respondsToSelector:@selector(CHLabel:tapOnKeyWord:)])
- {
- [delegate CHLabel:self tapOnKeyWord:(NSString *)[dic valueForKey:@"option"]];
- }
- }
- }
- //获取coretext高度
- - (int)getAttributedStringHeightWithString:(NSAttributedString *)string WidthValue:(int) width
- {
- int total_height = 0;
- //string 为要计算高度的NSAttributedString
- CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string);
- CGRect drawingRect = CGRectMake(0, 0, width, 1000); //这里的高要设置足够大
- CGMutablePathRef path = CGPathCreateMutable();
- CGPathAddRect(path, NULL, drawingRect);
- CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
- CGPathRelease(path);
- CFRelease(framesetter);
- NSArray *linesArray = (NSArray *) CTFrameGetLines(textFrame);
- CGPoint origins[[linesArray count]];
- CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins);
- int line_y = (int) origins[[linesArray count] -1].y; //最后一行line的原点y坐标
- CGFloat ascent;
- CGFloat descent;
- CGFloat leading;
- CTLineRef line = (CTLineRef) [linesArray objectAtIndex:[linesArray count]-1];
- CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
- total_height = 1000 - line_y + (int) descent +1; //+1为了纠正descent转换成int小数点后舍去的值
- CFRelease(textFrame);
- return total_height;
- }
- @end
- TestViewController.h 代码实现:
- @interface TestViewController : UIViewController <CHLabelDelegate>
- {
- IBOutlet UITextField *textString;
- IBOutlet UITextField *keyString;
- }
- - (IBAction) showText:(id)sender;
- @end
- #import "TestViewController.h"
- @interface TestViewController ()
- @end
- @implementation TestViewController
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- // Custom initialization
- }
- return self;
- }
- - (IBAction) showText:(id)sender
- {
- [textString resignFirstResponder];
- [keyString resignFirstResponder];
- CHLabel *label = [[CHLabel alloc] initWithFrame:CGRectMake(10, 260, 300, 200)];
- [label setUserInteractionEnabled:YES];
- [label setText:textString.text andKeyWord:keyString.text];
- [label setTextColor:[UIColor redColor] andKeyWordColor:[UIColor blueColor]];
- [label setTextUnderlineStyle:kCHLabelUnderlineStyleSingle andKeyWordUnderlineStyle:kCHLabelUnderlineStyleDouble];
- [label setTextFont:[UIFont systemFontOfSize:20] andKeyWordFont:[UIFont boldSystemFontOfSize:30]];
- label.backgroundColor = [UIColor lightGrayColor];
- [label setNumberOfLines:0];
- label.delegate = self;
- NSArray *fontArray = [UIFont familyNames];
- NSString *fontName;
- if ([fontArray count]) {
- fontName = [fontArray objectAtIndex:0];
- }
- [label setFont:[UIFont fontWithName:fontName size:20]];
- [self.view addSubview:label];
- // [label setNeedsDisplay];
- [label release];
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- }
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- }
- #pragma mark CHLabelDelegate
- - (void) CHLabel:(CHLabel *) chLabel tapOnKeyWord:(NSString *) keyWord
- {
- UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"notice"
- message:[NSString stringWithFormat:@"Tap on keyWord:%@", keyWord]
- delegate:nil
- cancelButtonTitle:@"OK"
- otherButtonTitles:nil];
- [alert show];
- [alert release];
}
完整的项目链接:http://pan.baidu.com/share/link?shareid=362100&uk=3674861929
转载请保留,原文链接:http://blog.csdn.net/zfpp25_/article/details/8639215
若发现有不合适或错误之处,还请批评指正,不胜感激。