棄坑簡書,從簡書搬家到掘金,正好把以前這篇文章改成Markdown模式。git
本文是技術集中的第一篇技術性文章,因此就記錄一點簡單且淺顯易懂的東西。github
如今即時通信和朋友圈這兩塊功能基本上屬於app的標配功能了吧。圖文混排在這兩塊中使用最爲常見,我已經作好了demo:圖文混排Demo。正則表達式
文中會講述幾點小技巧:圖文混排、動態計算文字長度、圖片拉伸方法。數組
在之前作圖文混排的時候,常常使用OHAttributedLabel
,後來蘋果吸收了一些第三方的優勢,對NSString
作了擴展,做者也再也不更新,推薦用系統的方法來實現圖文混排。具體請自行百度或者google關鍵字OHAttributedLabel
。bash
蘋果在iOS7中推出了一個新的類NSTextAttachment
,它是作圖文混排的利器,本文就是用這個類,只用50行代碼實現文字與表情混排,固然也能夠實現段落中的圖文混排,與CoreText比起來實在是簡單了太多,下面講述兩個案例。(更新:YYKit中的YYTextAttachment,應該就是從NSTextAttachment上找的靈感吧)app
先上效果圖,聊天界面中的圖文混排工具
要實現這樣的效果,code4app上彷佛有不少種作法,還有一些奇葩的一個字符一個label,可是今天要講述的作法,是目前爲止我看到的最簡單的作法了,只用一個UILabel,須要用到UILabel的attributedText屬性。ui
首先,須要組裝一個表情和文字對應的plist文件,plist中的鍵值對以下:google
本文用一個工具類來實現一個轉換的方法,你也能夠給NSString添加一個類別來實現。spa
第一步,解析plist文件,轉化爲數組。
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"emoticons" ofType:@"plist"];
NSArray *face = [NSArray arrayWithContentsOfFile:filePath];
複製代碼
第二步,將字符串轉換爲可變屬性字符串,並經過正則表達式匹配出全部的要替換的字符。
//一、建立一個可變的屬性字符串
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:text];
//二、經過正則表達式來匹配字符串
NSString *regex_emoji = @"\\[[a-zA-Z0-9\\/\\u4e00-\\u9fa5]+\\]";//匹配表情
NSError *error =nil;
NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:regex_emoji options:NSRegularExpressionCaseInsensitive error:&error];
if (!re) {
NSLog(@"%@", [errorlocalizedDescription]);
return attributeString;
}
NSArray *resultArray = [rematchesInString:text options:0 range:NSMakeRange(0, text.length)];
複製代碼
數組中都是NSTextCheckingResult對象,它包含了特殊字符在整個字符串中的位置等信息。
第三步,將特殊字符與對應表情關聯
NSMutableArray *imageArray = [NSMutableArray arrayWithCapacity:resultArray.count];
//根據匹配範圍來用圖片進行相應的替換
for(NSTextCheckingResult *match in resultArray) {
//獲取數組元素中獲得range
NSRangerange = [match range];
//獲取原字符串中對應的值
NSString*subStr = [text substringWithRange:range];
for(inti =0; i < face.count; i ++) {
if ([face[i][@"cht"] isEqualToString:subStr]) {
//face[i][@"png"]就是咱們要加載的圖片
//新建文字附件來存放咱們的圖片,iOS7才新加的對象
NSTextAttachment*textAttachment = [[NSTextAttachment alloc] init];
//給附件添加圖片
textAttachment.image = [UIImage imageNamed:face[i][@"png"]];
//調整一下圖片的位置,若是你的圖片偏上或者偏下,調整一下bounds的y值便可
textAttachment.bounds = CGRectMake(0, -8, textAttachment.image.size.width, textAttachment.image.size.height);
//把附件轉換成可變字符串,用於替換掉源字符串中的表情文字
NSAttributedString*imageStr = [NSAttributedString attributedStringWithAttachment:textAttachment];
//把圖片和圖片對應的位置存入字典中
NSMutableDictionary*imageDic = [NSMutableDictionary dictionaryWithCapacity:2];
[imageDic setObject:imageStr forKey:@"image"];
[imageDic setObject:[NSValuevalueWithRange:range] forKey:@"range"];
//把字典存入數組中
[imageArray addObject:imageDic];
}
}
}
複製代碼
第四步,將特殊字符替換成圖片
// 四、從後往前替換,不然會引發位置問題
for (int i = (int)imageArray.count-1; i >=0; i--) {
NSRange range;
[imageArray[i][@"range"] getValue:&range];
//進行替換
[attributeString replaceCharactersInRange:range withAttributedString:imageArray[i][@"image"]];
}
複製代碼
用法:
NSString *content = @"文字加上表情[得意][酷][呲牙]";
NSMutableAttributedString *attrStr = [Utility emotionStrWithString:content];
_contentLabel.attributedText= attrStr;
複製代碼
須要實現的效果:
有了上面的方法,這個效果更容易實現,只須要將某些圖片給它設置一個固定的字符對應便可。
與以上方法主要不一樣點在於正則表達式:
//二、匹配字符串
NSError *error = nil;
NSRegularExpression *re = [NSRegularExpression regularExpressionWithPattern:string options:NSRegularExpressionCaseInsensitive error:&error];
if (!re) {
NSLog(@"%@", [error localizedDescription]);
return attributeString;
}
複製代碼
用法:
NSString *praiseStr = @"路人甲、路人乙";
NSString *praiseInfo = [NSStringstringWithFormat:@"<點贊> %@",praiseStr];
NSDictionary *attributesForAll = @{NSFontAttributeName:[UIFontsystemFontOfSize:14.0],NSForegroundColorAttributeName:[UIColorgrayColor]};
NSMutableAttributedString *attrStr = [Utility exchangeString:@"<點贊>" withText:praiseInfoimageName:@"dynamic_love_blue"];
複製代碼
一、計算動態文字的長度
NSMutableAttributedString *content = [Utility emotionStrWithString:_dynamic.text];
[content addAttribute:NSFontAttributeName value:kContentFont range:NSMakeRange(0, content.length)];
CGSize maxSize = CGSizeMake(kDynamicWidth,MAXFLOAT);
CGSize attrStrSize = [content boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin context:nil].size;
複製代碼
其中NSMutableAttributedString類型的字符串能夠添加多種屬性,而且在計算的時候必須設置字符大小等屬性。
二、圖片拉伸
在iOS5以前能夠用stretchableImageWithLeftCapWidth: topCapHeight:
iOS5之中用resizableImageWithCapInsets:
iOS6開始多了一個參數resizableImageWithCapInsets:resizingMode: