JXEmoji.m 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. //
  2. // JXEmoji.m
  3. // sjvodios
  4. //
  5. // Created by jixiong on 13-7-9.
  6. //
  7. //
  8. #import "JXEmoji.h"
  9. #import "FaceViewController.h"
  10. #import "emojiViewController.h"
  11. #import <CoreText/CoreText.h>
  12. @implementation JXEmoji
  13. @synthesize maxWidth,faceHeight,faceWidth,offset;
  14. #define BEGIN_FLAG @"["
  15. #define END_FLAG @"]"
  16. static NSArray *faceArray;
  17. static NSMutableArray *imageArray;
  18. - (id)initWithFrame:(CGRect)frame
  19. {
  20. self = [super initWithFrame:frame];
  21. if (self) {
  22. if(faceArray==nil){
  23. /*
  24. faceArray = [[NSArray alloc]initWithObjects:@"[微笑]",@"[撇嘴]",@"[色]",@"[发呆]",@"[得意]",@"[流泪]",@"[害羞]",@"[闭嘴]",@"[睡]",@"[大哭]",
  25. @"[尴尬]",@"[发怒]",@"[调皮]",@"[龇牙]",@"[惊讶]",@"[难过]",@"[严肃]",@"[冷汗]",@"[抓狂]",@"[吐]",@"[偷笑]",@"[可爱]",@"[白眼]",@"[傲慢]",
  26. @"[饥饿]",@"[困]",@"[惊恐]",@"[流汗]",@"[憨笑]",@"[大兵]",@"[奋斗]",@"[咒骂]",@"[疑问]",@"[嘘]",@"[晕]",@"[折磨]",@"[衰]",@"[骷髅]",
  27. @"[敲打]",@"[再见]",@"[擦汗]",@"[抠鼻]",@"[鼓掌]",@"[糗大了]",@"[坏笑]",@"[左哼哼]",@"[右哼哼]",@"[哈欠]",@"[鄙视]",@"[委屈]",@"[快哭了]",
  28. @"[阴险]",@"[亲嘴]",@"[吓]",@"[可怜]",@"[菜刀]",@"[西瓜]",@"[啤酒]",@"[篮球]",@"[乒乓]",@"[咖啡]",@"[饭]",@"[猪头]",@"[玫瑰]",@"[凋谢]",
  29. @"[示爱]",@"[爱心]",@"[心碎]",@"[蛋糕]",@"[闪电]",@"[炸弹]",@"[刀]",@"[足球]",@"[瓢虫]",@"[便便]",@"[拥抱]",@"[月亮]",@"[太阳]",@"[礼物]",
  30. @"[强]",@"[弱]",@"[握手]",@"[胜利]",@"[抱拳]",@"[勾引]",@"[拳头]",@"[差劲]",@"[爱你]",@"[NO]",@"[OK]",@"[苹果]",@"[可爱狗]",@"[小熊]",@"[彩虹]",@"[皇冠]",@"[钻石]",nil];
  31. imageArray = [[NSMutableArray alloc] init];
  32. for (int i = 0;i<[faceArray count];i++){
  33. // NSString* s = [NSString stringWithFormat:@"%@f%.3d.png",[self imageFilePath],i];
  34. NSString* s = [NSString stringWithFormat:@"f%.3d.png",i];
  35. [imageArray addObject:s];
  36. }*/
  37. faceArray = g_faceVC.faceArray;
  38. imageArray = g_faceVC.imageArray;
  39. }
  40. data = [[NSMutableArray alloc] init];
  41. faceWidth = 18;
  42. faceHeight = 18;
  43. _top = 0;
  44. offset = 0;
  45. maxWidth = frame.size.width;
  46. self.numberOfLines = 0;
  47. self.lineBreakMode = NSLineBreakByWordWrapping;
  48. self.textAlignment = NSTextAlignmentLeft;
  49. self.userInteractionEnabled = YES;
  50. }
  51. return self;
  52. }
  53. -(void)dealloc{
  54. [data release];
  55. [super dealloc];
  56. }
  57. -(void) drawRect:(CGRect)rect
  58. {
  59. [self.textColor set];
  60. if( [data count]==1){
  61. if (![self.text hasPrefix:BEGIN_FLAG] && ![self.text hasSuffix:END_FLAG]){
  62. [super drawRect:rect];
  63. return;
  64. }
  65. }
  66. CGFloat upX=0;
  67. CGFloat upY=0;
  68. // NSLog(@"%f,%f,%f,%f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
  69. for (int i=0;i<[data count];i++) {
  70. NSString *str=[data objectAtIndex:i];
  71. unsigned long n = NSNotFound;
  72. if ([str hasPrefix:BEGIN_FLAG]&&[str hasSuffix:END_FLAG]) {
  73. n = [faceArray indexOfObject:str];
  74. if(n != NSNotFound){
  75. NSString *imageName = [imageArray objectAtIndex:n];
  76. UIImage *img=[UIImage imageNamed:imageName];
  77. [img drawInRect:CGRectMake(upX, upY+_top, faceWidth, faceHeight)];
  78. upX=faceWidth+upX;
  79. if (upX >= maxWidth)
  80. {
  81. upY = upY + faceHeight;
  82. upX = 0;
  83. }
  84. // NSLog(@"%@,%f,%f",str,upX,upY);
  85. }
  86. }
  87. if(n == NSNotFound){
  88. for (int j = 0; j < [str length]; j++) {
  89. NSString *temp = [str substringWithRange:NSMakeRange(j, 1)];
  90. if([temp isEqualToString:@"\n"]){
  91. upY = upY + _size;
  92. upX = 0;
  93. }else{
  94. CGSize size=[temp sizeWithFont:self.font constrainedToSize:CGSizeMake(_size, _size)];
  95. [temp drawInRect:CGRectMake(upX, upY+_top, size.width, size.height) withFont:self.font];
  96. upX=upX+size.width;
  97. if (upX >= maxWidth)
  98. {
  99. upY = upY + size.height;
  100. upX = 0;
  101. }
  102. }
  103. // NSLog(@"%@,%f,%f",temp,upX,upY);
  104. }
  105. }
  106. }
  107. }
  108. //判断是否含有表情
  109. - (BOOL)isContainsEmoji:(NSString *)string {
  110. __block BOOL isEomji = NO;
  111. [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
  112. const unichar hs = [substring characterAtIndex:0];
  113. // surrogate pair
  114. if (0xd800 <= hs && hs <= 0xdbff) {
  115. if (substring.length > 1) {
  116. const unichar ls = [substring characterAtIndex:1];
  117. const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
  118. if (0x1d000 <= uc && uc <= 0x1f77f) {
  119. isEomji = YES;
  120. }
  121. }
  122. } else {
  123. // non surrogate
  124. if (0x2100 <= hs && hs <= 0x27ff && hs != 0x263b) {
  125. isEomji = YES;
  126. } else if (0x2B05 <= hs && hs <= 0x2b07) {
  127. isEomji = YES;
  128. } else if (0x2934 <= hs && hs <= 0x2935) {
  129. isEomji = YES;
  130. } else if (0x3297 <= hs && hs <= 0x3299) {
  131. isEomji = YES;
  132. } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50|| hs == 0x231a ) {
  133. isEomji = YES;
  134. }
  135. if (!isEomji && substring.length > 1) {
  136. const unichar ls = [substring characterAtIndex:1];
  137. if (ls == 0x20e3) {
  138. isEomji = YES;
  139. }
  140. }
  141. }
  142. }];
  143. return isEomji;
  144. }
  145. //将表情和文字分开,装进array
  146. -(void)getImageRange:(NSString*)message array: (NSMutableArray*)array {
  147. NSRange range=[message rangeOfString: BEGIN_FLAG];
  148. NSRange range1=[message rangeOfString: END_FLAG];
  149. //判断当前字符串是否还有表情的标志。
  150. self.contentEmoji = [self isContainsEmoji:message];
  151. if (range.length>0 && range1.length>0) {
  152. self.contentEmoji = YES;
  153. if (range.location > 0) {
  154. [array addObject:[message substringToIndex:range.location]];
  155. [array addObject:[message substringWithRange:NSMakeRange(range.location, range1.location+1-range.location)]];
  156. NSString *str=[message substringFromIndex:range1.location+1];
  157. [self getImageRange:str array:array];
  158. }else {
  159. NSString *nextstr=[message substringWithRange:NSMakeRange(range.location, range1.location+1-range.location)];
  160. //排除文字是“”的
  161. if (![nextstr isEqualToString:@""]) {
  162. [array addObject:nextstr];
  163. NSString *str=[message substringFromIndex:range1.location+1];
  164. [self getImageRange:str array:array];
  165. }else {
  166. return;
  167. }
  168. }
  169. } else if (message != nil) {
  170. [array addObject:message];
  171. }
  172. }
  173. //获取特殊文本的范围
  174. #pragma mark ------------特殊字符-----------------
  175. -(void)setAttributedTextRange:(NSString *)text{
  176. NSError *error = NULL;
  177. NSString * patren = @"[^0-9]";
  178. NSRegularExpression * reg = [NSRegularExpression regularExpressionWithPattern:patren options:0 error:&error];
  179. NSString * numberString = [reg stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, text.length) withTemplate:@" "];
  180. //提取所有数字串
  181. NSArray * array = [numberString componentsSeparatedByString:@" "];
  182. NSMutableArray * numberArr = [[NSMutableArray alloc]init];
  183. //除去空格,并在手机号前后加空格
  184. NSMutableString * muText = [[NSMutableString alloc]initWithString:text];
  185. //因为插入空格后位置发生变化
  186. int plus = 0;
  187. for (int i = 0; i < [array count]; i++) {
  188. NSString * number = array[i];
  189. if (![number isEqualToString:@""] && number.length >5) {
  190. NSRange range = [text rangeOfString:number];
  191. [muText insertString:@" " atIndex:range.location +plus*2];
  192. [muText insertString:@" " atIndex:(range.location + range.length+1+plus*2)];
  193. //保存空格位置,以后删除
  194. [numberArr addObject:[NSNumber numberWithInteger:range.location]];
  195. [numberArr addObject:[NSNumber numberWithInteger:(range.location + range.length)]];
  196. plus++;
  197. }
  198. }
  199. text = muText;
  200. NSDataDetector *detector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypePhoneNumber|NSTextCheckingTypeLink error:&error];
  201. self.matches = [detector matchesInString:text options:0 range:NSMakeRange(0, text.length)];
  202. [self highlightLinksWithIndex:NSNotFound];
  203. //删除之前添加的空格
  204. for (int i = 0; i < [numberArr count]; i++) {
  205. NSNumber * index = numberArr[i];
  206. [muText deleteCharactersInRange:NSMakeRange([index integerValue], 1)];
  207. }
  208. text = muText;
  209. }
  210. - (BOOL)isIndex:(CFIndex)index inRange:(NSRange)range {
  211. return index > range.location && index < range.location+range.length;
  212. }
  213. - (void)highlightLinksWithIndex:(CFIndex)index {
  214. if(self.contentEmoji){
  215. return;
  216. }
  217. NSMutableAttributedString* attributedString = [self.attributedText mutableCopy];
  218. //因为之前添加空格位置发生变化
  219. int plus = 0;
  220. for (NSTextCheckingResult *match in self.matches) {
  221. if ([match resultType] == NSTextCheckingTypePhoneNumber||[match resultType] == NSTextCheckingTypeLink) {
  222. NSRange matchRange;
  223. if ([match resultType] == NSTextCheckingTypePhoneNumber) {
  224. matchRange = NSMakeRange(match.range.location -1 -2*plus, match.range.length);
  225. plus++;
  226. }else{
  227. matchRange = NSMakeRange(match.range.location -2*plus, match.range.length);
  228. }
  229. // if (matchRange.location == 18446744073709551615 &&matchRange.length !=0) {
  230. // matchRange.location =0;
  231. // }
  232. //被点击时吗,判断index在range蓝色字体范围内,则变灰,默认为蓝色
  233. if ([self isIndex:index inRange:matchRange]) {
  234. [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor grayColor] range:matchRange];
  235. }
  236. else {
  237. [attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:matchRange];
  238. }
  239. //添加下划线
  240. if ([match resultType] == NSTextCheckingTypeLink) {
  241. [attributedString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:matchRange];
  242. }
  243. }
  244. }
  245. self.attributedText = attributedString;
  246. }
  247. //被点击时获取特殊字符的位置
  248. - (CFIndex)characterIndexAtPoint:(CGPoint)point {
  249. ////////
  250. NSMutableAttributedString* optimizedAttributedText = [self.attributedText mutableCopy];
  251. // use label's font and lineBreakMode properties in case the attributedText does not contain such attributes
  252. [self.attributedText enumerateAttributesInRange:NSMakeRange(0, [self.attributedText length]) options:0 usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
  253. if (!attrs[(NSString*)kCTFontAttributeName]) {
  254. [optimizedAttributedText addAttribute:(NSString*)kCTFontAttributeName value:self.font range:NSMakeRange(0, [self.attributedText length])];
  255. }
  256. if (!attrs[(NSString*)kCTParagraphStyleAttributeName]) {
  257. NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
  258. [paragraphStyle setLineBreakMode:self.lineBreakMode];
  259. [optimizedAttributedText addAttribute:(NSString*)kCTParagraphStyleAttributeName value:paragraphStyle range:range];
  260. }
  261. }];
  262. // modify kCTLineBreakByTruncatingTail lineBreakMode to kCTLineBreakByWordWrapping
  263. [optimizedAttributedText enumerateAttribute:(NSString*)kCTParagraphStyleAttributeName inRange:NSMakeRange(0, [optimizedAttributedText length]) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
  264. NSMutableParagraphStyle* paragraphStyle = [value mutableCopy];
  265. if ([paragraphStyle lineBreakMode] == kCTLineBreakByTruncatingTail) {
  266. [paragraphStyle setLineBreakMode:kCTLineBreakByWordWrapping];
  267. }
  268. [optimizedAttributedText removeAttribute:(NSString*)kCTParagraphStyleAttributeName range:range];
  269. [optimizedAttributedText addAttribute:(NSString*)kCTParagraphStyleAttributeName value:paragraphStyle range:range];
  270. }];
  271. ////////
  272. if (!CGRectContainsPoint(self.bounds, point)) {
  273. return NSNotFound;
  274. }
  275. CGRect textRect = [self textRect];
  276. if (!CGRectContainsPoint(textRect, point)) {
  277. return NSNotFound;
  278. }
  279. // Offset tap coordinates by textRect origin to make them relative to the origin of frame
  280. point = CGPointMake(point.x - textRect.origin.x, point.y - textRect.origin.y);
  281. // Convert tap coordinates (start at top left) to CT coordinates (start at bottom left)
  282. point = CGPointMake(point.x, textRect.size.height - point.y);
  283. //////
  284. CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)optimizedAttributedText);
  285. CGMutablePathRef path = CGPathCreateMutable();
  286. CGPathAddRect(path, NULL, textRect);
  287. CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [self.attributedText length]), path, NULL);
  288. if (frame == NULL) {
  289. CFRelease(path);
  290. return NSNotFound;
  291. }
  292. CFArrayRef lines = CTFrameGetLines(frame);
  293. NSInteger numberOfLines = self.numberOfLines > 0 ? MIN(self.numberOfLines, CFArrayGetCount(lines)) : CFArrayGetCount(lines);
  294. //NSLog(@"num lines: %d", numberOfLines);
  295. if (numberOfLines == 0) {
  296. CFRelease(frame);
  297. CFRelease(path);
  298. return NSNotFound;
  299. }
  300. NSUInteger idx = NSNotFound;
  301. CGPoint lineOrigins[numberOfLines];
  302. CTFrameGetLineOrigins(frame, CFRangeMake(0, numberOfLines), lineOrigins);
  303. for (CFIndex lineIndex = 0; lineIndex < numberOfLines; lineIndex++) {
  304. CGPoint lineOrigin = lineOrigins[lineIndex];
  305. CTLineRef line = CFArrayGetValueAtIndex(lines, lineIndex);
  306. // Get bounding information of line
  307. CGFloat ascent, descent, leading, width;
  308. width = CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
  309. CGFloat yMin = floor(lineOrigin.y - descent);
  310. CGFloat yMax = ceil(lineOrigin.y + ascent);
  311. // Check if we've already passed the line
  312. if (point.y > yMax) {
  313. break;
  314. }
  315. // Check if the point is within this line vertically
  316. if (point.y >= yMin) {
  317. // Check if the point is within this line horizontally
  318. if (point.x >= lineOrigin.x && point.x <= lineOrigin.x + width) {
  319. // Convert CT coordinates to line-relative coordinates
  320. CGPoint relativePoint = CGPointMake(point.x - lineOrigin.x, point.y - lineOrigin.y);
  321. idx = CTLineGetStringIndexForPosition(line, relativePoint);
  322. break;
  323. }
  324. }
  325. }
  326. CFRelease(frame);
  327. CFRelease(path);
  328. return idx;
  329. }
  330. //上面的方法调用
  331. - (CGRect)textRect {
  332. CGRect textRect = [self textRectForBounds:self.bounds limitedToNumberOfLines:self.numberOfLines];
  333. textRect.origin.y = (self.bounds.size.height - textRect.size.height)/2;
  334. if (self.textAlignment == NSTextAlignmentCenter) {
  335. textRect.origin.x = (self.bounds.size.width - textRect.size.width)/2;
  336. }
  337. if (self.textAlignment == NSTextAlignmentRight) {
  338. textRect.origin.x = self.bounds.size.width - textRect.size.width;
  339. }
  340. return textRect;
  341. }
  342. -(void) setText:(NSString *)text{
  343. [super setText:text];
  344. [data removeAllObjects];
  345. [self getImageRange:text array:data];
  346. _size = self.font.pointSize;
  347. // maxWidth = self.frame.size.width+offset;
  348. maxWidth = self.frame.size.width-_size*0.5;
  349. CGFloat upX = 0;
  350. CGFloat upY = _size+6;
  351. BOOL isMoreLine=NO;
  352. if (data) {
  353. for (int i=0;i<[data count];i++) {
  354. NSString *str=[data objectAtIndex:i];
  355. BOOL isFace = NO;
  356. //是表情
  357. if ([str hasPrefix:BEGIN_FLAG]&&[str hasSuffix:END_FLAG]) {
  358. isFace = [faceArray indexOfObject:str] != NSNotFound;
  359. if(isFace){
  360. upX=faceWidth+upX;
  361. if (upX >= maxWidth)
  362. {
  363. upY = upY + faceHeight;
  364. upX = 0;
  365. isMoreLine = YES;
  366. }
  367. }
  368. }
  369. //不是表情
  370. if(!isFace) {
  371. for (int j = 0; j < [str length]; j++) {
  372. NSString *temp = [str substringWithRange:NSMakeRange(j, 1)];
  373. if([temp isEqualToString:@"\n"]){
  374. upY = upY + _size;
  375. upX = 0;
  376. isMoreLine = YES;
  377. }else{
  378. CGSize size=[temp sizeWithFont:self.font constrainedToSize:CGSizeMake(_size, _size)];
  379. upX=upX+size.width;
  380. if (upX >= maxWidth)
  381. {
  382. upY = upY + size.height;
  383. upX = 0;
  384. isMoreLine = YES;
  385. }
  386. }
  387. }
  388. }
  389. }
  390. }
  391. if(upY<self.frame.size.height){
  392. _top = (self.frame.size.height-upY)/2;
  393. // NSLog(@"_top=%d/%d",_top,self.frame.size.height);
  394. }
  395. if(upY<_size)
  396. upY = _size;
  397. if(upY<self.frame.size.height)
  398. upY = self.frame.size.height;
  399. if(isMoreLine)
  400. upX = self.frame.size.width;
  401. else
  402. upX = upX+_size;
  403. self.frame = CGRectMake(self.frame.origin.x,self.frame.origin.y, upX, upY); //@ 需要将该view的尺寸记下,方便以后使用
  404. // NSLog(@"%d,%.1f %.1f", [data count], upX, upY);
  405. if (!self.contentEmoji) {
  406. if (text == nil) {
  407. return;
  408. }
  409. [self setAttributedTextRange:text];
  410. }
  411. }
  412. #pragma mark ---------------点击事件----------------
  413. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
  414. self.lastTouches = touches;
  415. UITouch *touch = [touches anyObject];
  416. CFIndex index = [self characterIndexAtPoint:[touch locationInView:self]];
  417. if (![self label:self didBeginTouch:touch onCharacterAtIndex:index]) {
  418. [super touchesBegan:touches withEvent:event];
  419. }
  420. }
  421. - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
  422. // self.lastTouches = touches;
  423. UITouch *touch = [touches anyObject];
  424. CFIndex index = [self characterIndexAtPoint:[touch locationInView:self]];
  425. if (![self label:self didMoveTouch:touch onCharacterAtIndex:index]) {
  426. [super touchesMoved:touches withEvent:event];
  427. }
  428. }
  429. - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
  430. if (!self.lastTouches) {
  431. return;
  432. }
  433. self.lastTouches = nil;
  434. UITouch *touch = [touches anyObject];
  435. CFIndex index = [self characterIndexAtPoint:[touch locationInView:self]];
  436. if (![self label:self didEndTouch:touch onCharacterAtIndex:index]) {
  437. [super touchesEnded:touches withEvent:event];
  438. }
  439. }
  440. - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
  441. if (!self.lastTouches) {
  442. return;
  443. }
  444. self.lastTouches = nil;
  445. UITouch *touch = [touches anyObject];
  446. if (![self label:self didCancelTouch:touch]) {
  447. [super touchesCancelled:touches withEvent:event];
  448. }
  449. }
  450. - (void)cancelCurrentTouch {
  451. if (self.lastTouches) {
  452. [self label:self didCancelTouch:[self.lastTouches anyObject]];
  453. self.lastTouches = nil;
  454. }
  455. }
  456. #pragma mark -------------点击处理------------------
  457. - (BOOL)label:(JXEmoji *)label didBeginTouch:(UITouch *)touch onCharacterAtIndex:(CFIndex)charIndex {
  458. [self highlightLinksWithIndex:charIndex];
  459. }
  460. - (BOOL)label:(JXEmoji *)label didMoveTouch:(UITouch *)touch onCharacterAtIndex:(CFIndex)charIndex {
  461. [self highlightLinksWithIndex:charIndex];
  462. }
  463. //这里对文本的电话号码处理
  464. - (BOOL)label:(JXEmoji *)label didEndTouch:(UITouch *)touch onCharacterAtIndex:(CFIndex)charIndex {
  465. [self highlightLinksWithIndex:NSNotFound];
  466. int plus = 0;
  467. for (NSTextCheckingResult *match in self.matches) {
  468. if ([match resultType] == NSTextCheckingTypePhoneNumber) {
  469. NSRange matchRange = NSMakeRange(match.range.location -1 -2*plus, match.range.length);
  470. self.copyText = match.phoneNumber;
  471. if ([self isIndex:charIndex inRange:matchRange]) {
  472. UIActionSheet * action =[[UIActionSheet alloc]initWithTitle:nil
  473. delegate:self
  474. cancelButtonTitle:@"取消"
  475. destructiveButtonTitle:@"拨打电话"
  476. otherButtonTitles:@"复制", nil];
  477. action.tag =1;
  478. [action showInView:[UIApplication sharedApplication].keyWindow];
  479. break;
  480. }
  481. plus++;
  482. }else if ([match resultType] == NSTextCheckingTypeLink){
  483. NSRange matchRange = NSMakeRange(match.range.location -2*plus, match.range.length);
  484. self.copyText = [NSString stringWithFormat:@"%@",match.URL];
  485. if ([self isIndex:charIndex inRange:matchRange]) {
  486. UIActionSheet * action =[[UIActionSheet alloc]initWithTitle:nil
  487. delegate:self
  488. cancelButtonTitle:@"取消"
  489. destructiveButtonTitle:@"打开网址"
  490. otherButtonTitles:@"复制", nil];
  491. action.tag=2;
  492. [action showInView:[UIApplication sharedApplication].keyWindow];
  493. break;
  494. }
  495. }
  496. }
  497. }
  498. #pragma -mark actionSheet回调方法
  499. -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
  500. {
  501. self.backgroundColor=[UIColor clearColor];
  502. if (actionSheet.tag==1) {
  503. //打电话
  504. if(buttonIndex==0){
  505. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"tel://%@",self.copyText]]];
  506. }else if(buttonIndex==1){//复制
  507. UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  508. [pasteboard setString:self.copyText];
  509. }
  510. }else if (actionSheet.tag==2){
  511. //打开网址
  512. if(buttonIndex==0){
  513. [[UIApplication sharedApplication] openURL:[NSURL URLWithString:self.copyText]];
  514. }else if(buttonIndex==1){//复制
  515. UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  516. [pasteboard setString:self.copyText];
  517. }
  518. }
  519. }
  520. - (BOOL)label:(JXEmoji *)label didCancelTouch:(UITouch *)touch {
  521. [self highlightLinksWithIndex:NSNotFound];
  522. }
  523. @end