ios知识点总结——富文本实现图文混排
在iOS开发中经常会遇到一些图文混排的情况,特别是在微博类应用的开发过程中经常会遇到各种表情,各种链接的解析。笔者在实践开发中经历了几次这种类型的开发,由最开始的利用WebView进行布局到最后利用富文本进行布局,对该部分的开发积累了一定的经验,现对富文本与正则表达式混用实现图文混排进行总结:
一.富文本
WebView虽然也可以实现图文混排的效果,但是在使用的时候比较复杂,而且WebVIew的内存泄漏相当明显,使用不好反而得补偿失。现在很多的新闻类App都采用自己写的富文本进行图文混排。在很多情况下,富文本表现予外的是一个Label,将要显示的内容通过正则等封装成HTML字符串,然后显示在界面上,
下面就是按照步骤实现这一功能:
(1)先下载已经封装好的富文本标签类RCLabel(http://www.okbase.net/file/item/20694)
该类是由一牛人封装好的用于实现图文混排的富文本类,在下载下来的源代码中可以看到其用法,但是这里有一个较为复杂的问题是你每次都需要手动将你要显示的内容封装成HTML格式的文本,这个过程相当繁琐而且容易出错,所以我在这个基础上进行了改进,将封装HTML的方法通过正则表达式独立开来,这样就实现了RCLabel与正则实现图文混排,以下是代码:
将字符串转化成HTML的正则如下:
.h文件
#import <Foundation/Foundation.h>
@interface HtmlString: NSString
+ (NSString *)transformString:(NSString *)originalStr;
@end
.m 文件如下:
#import "HtmlString.h"
#import <Foundation/NSObjCRuntime.h>
#import "RegexKitLite.h"
@implementation HtmlString
+ (NSString *)transformString:(NSString *)originalStr
{
NSString *text =originalStr;
//解析http://短链接
NSString *regex_http =@"http(s)?://([a-zA-Z|\\d]+\\.)+[a-zA-Z|\\d]+(/[a-zA-Z|\\d|\\-|\\+|_./?%&=]*)?";//http://短链接正则表达式
NSArray *array_http =[text componentsMatchedByRegex:regex_http];
if ([array_http count]) {
for (NSString *strin array_http) {
NSRange range = [text rangeOfString:str];
NSString *funUrlStr = [NSStringstringWithFormat:@"<ahref=%@>%@</a>",str, str];
text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, str.length)withString:funUrlStr];
}
}
//解析@
NSString *regex_at =@"@[\\u4e00-\\u9fa5\\w\\-]+";//@的正则表达式
NSArray *array_at = [text componentsMatchedByRegex:regex_at];
if ([array_at count]) {
NSMutableArray *test_arr = [[NSMutableArrayalloc]init];
for (NSString *strin array_at) {
NSRange range = [text rangeOfString:str];
if (![test_arr containsObject:str]){
[test_arr addObject:str];
NSString *funUrlStr = [NSStringstringWithFormat:@"<ahref=%@>%@</a>",str, str];
text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [str length]) withString:funUrlStr];
}
}
[test_arr release];
}
//解析&
NSString *regex_dot =@"\\$\\*?[\u4e00-\u9fa5|a-zA-Z|\\d]{2,8}(\\((SH|SZ)?\\d+\\))?";//&的正则表达式
NSArray *array_dot = [text componentsMatchedByRegex:regex_dot];
if ([array_dot count]) {
NSMutableArray *test_arr = [[NSMutableArrayalloc]init];
for (NSString *strin array_dot) {
NSRange range = [text rangeOfString:str];
if (![test_arr containsObject:str]){
[test_arr addObject:str];
NSString *funUrlStr = [NSStringstringWithFormat:@"<ahref=%@>%@</a>",str, str];
text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [str length]) withString:funUrlStr];
}
}
[test_arr release];
}
//解析话题
NSString *regex_pound = @"#([^\\#|.]+)#";//话题的正则表达式
NSArray *array_pound =[text componentsMatchedByRegex:regex_pound];
if ([array_pound count]) {
for (NSString *strin array_pound) {
NSRange range = [text rangeOfString:str];
NSString *funUrlStr = [NSStringstringWithFormat:@"<ahref=%@>%@</a>",str, str];
text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [strlength])withString:funUrlStr];
}
}
//解析表情
NSString *regex_emoji =@"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\]";//表情的正则表达式
NSArray *array_emoji =[text componentsMatchedByRegex:regex_emoji];
NSString *filePath = [[[NSBundlemainBundle]resourcePath]stringByAppendingPathComponent:@"emotionImage.plist"];
NSDictionary *m_EmojiDic = [[NSDictionaryalloc]initWithContentsOfFile:filePath];
// NSString *path= [NSString stringWithFormat:@"%@", [[NSBundle mainBundle]bundlePath]];
if ([array_emoji count]) {
for (NSString *strin array_emoji) {
NSRange range = [text rangeOfString:str];
NSString *i_transCharacter= [m_EmojiDicobjectForKey:str];
if (i_transCharacter){
//NSString*imageHtml = [NSString stringWithFormat:@"<img src = 'file://%@/%@' width='12'height='12'>", path, i_transCharacter];
NSString *imageHtml = [NSStringstringWithFormat:@"<imgsrc =%@>", i_transCharacter];
text = [text stringByReplacingCharactersInRange:NSMakeRange(range.location, [str length]) withString:[imageHtmlstringByAppendingString:@""]];
}
}
}
[m_EmojiDic release];
//返回转义后的字符串
return text;
}
@end
那么在使用的时候如下:
// contentStr为你要显示的图文字符串
NSString *str =[HtmlStringtransformString:contentStr];
textLabel = [[RCLabelalloc]initWithFrame:CGRectMake(10,160,300,84)];
textLabel.delegate =self;
textLabel.sizeDelegate =self;
[textLabelsetFont:[UIFontfontWithName:TextNamesize:15]];
RCLabelComponentsStructure *componentsDS = [RCLabelextractTextStyle:textString];
textLabel.componentsAndPlainText = componentsDS;
CGSize optimalSize= [textLabeloptimumSize:YES]; //计算图文混排后的高度
textLabel.frame=CGRectMake(10,180,300,optimalSize.height+5);
textLabel.lineBreakMode =NSLineBreakByCharWrapping;
textLabel.backgroundColor = [UIColorclearColor];
textLabel.textColor = [UIColorcolorWithRed:33.0/255green:33.0/255blue:33.0/255alpha:1];
[self.viewaddSubview:textLabel];
如果你在实现图文混排时还有超链接、@、$等,在最后实现该类的代理方法
-(void)RCLabel:(id)RCLabeldidSelectLinkWithURL:(NSString *)url
{ // url为超链接的文字内容
}
效果图如下:
下面提供一个详细的图文混排的DEMO,该DEMO包含了AFJSONRequest的用法,异步加在图片的用法,以及RCLabel与正则表达的用法
请点击下载
效果图