1.里面主要兩個控件:
YYTextView 和 YYLabel
現(xiàn)在主要是YYTextview的簡單使用
YYText主要是NSMutableAttributedString來處理富文本 他的內(nèi)部實(shí)現(xiàn)可以自己去深究欲虚。
簡單的圖文并排能岩,使用NSMutableAttributedString創(chuàng)建一個對象 然后 appendAttributesString來拼接文字和圖片(占位)//
//??TextAndImageTextViewVC.h
//??YYTextDemo
//
//??Created?by?linpeng?on?16/3/13.
//??Copyright???2016年?ibireme.?All?rights?reserved.
//
#import
@interface?TextAndImageTextViewVC?:?UIViewController
@end
//
//??TextAndImageTextViewVC.m
//??YYTextDemo
//
//??Created?by?linpeng?on?16/3/13.
//??Copyright???2016年?ibireme.?All?rights?reserved.
//
#import?"TextAndImageTextViewVC.h"
#import?"YYText.h"
#import?"UIView+YYAdd.h"
#import?"YYTextView.h"
#import?"YYImage.h"
#import?"NSBundle+YYAdd.h"
#import?"NSString+YYAdd.h"
@interface?TextAndImageTextViewVC?()
@end
YYTextView?*textView;
@implementation?TextAndImageTextViewVC
-?(void)viewDidLoad?{
[super?viewDidLoad];
[self.view?setBackgroundColor:[UIColor?whiteColor]];
textView=?[[YYTextView?alloc]?initWithFrame:CGRectMake(0,?0,?0,?0)];
textView.userInteractionEnabled=YES;
textView.textVerticalAlignment=YYTextVerticalAlignmentTop;
textView.size=CGSizeMake(self.view.frame.size.width,?self.view.frame.size.height);
//創(chuàng)建最主要的attribute文本
NSMutableAttributedString?*contentText=?[NSMutableAttributedString?new];
UIFont?*font=?[UIFont?systemFontOfSize:16];
//圖片資源
YYImage?*image=?[YYImage?imageNamed:@"demo.jpg"];
image.preloadAllAnimatedImageFrames=YES;
//添加文本+圖片
[contentText?appendAttributedString:[[NSAttributedString?alloc]?initWithString:@"這是第一站圖片"?attributes:nil]];
{
YYAnimatedImageView?*imageView=?[[YYAnimatedImageView?alloc]?initWithImage:image];
imageView.frame=CGRectMake(0,?0,?textView.width?-?10,?textView.width/image.size.width*image.size.height);
NSMutableAttributedString?*attachText=?[NSMutableAttributedString?yy_attachmentStringWithContent:imageView?contentMode:UIViewContentModeScaleAspectFit?attachmentSize:imageView.size?alignToFont:font?alignment:YYTextVerticalAlignmentCenter];
[contentText?appendAttributedString:attachText];
}
//添加文本+圖片
[contentText?appendAttributedString:[[NSAttributedString?alloc]?initWithString:@"\n?接下來是第二張"?attributes:nil]];
{
YYAnimatedImageView?*imageView2=?[[YYAnimatedImageView?alloc]?initWithImage:image];
imageView2.frame=CGRectMake(0,?0,?textView.width?-?10,?textView.width/image.size.width*image.size.height);
NSMutableAttributedString?*attachText2=?[NSMutableAttributedString?yy_attachmentStringWithContent:imageView2?contentMode:UIViewContentModeScaleAspectFit?attachmentSize:imageView2.size?alignToFont:font?alignment:YYTextVerticalAlignmentCenter];
[contentText?appendAttributedString:attachText2];
}
textView.attributedText=contentText;
[self.view?addSubview:textView];
//獲取圖片資源
NSArray?*attachments=textView.textLayout.attachments;
for(YYTextAttachment?*attachment?in?attachments)
{
YYAnimatedImageView?*imageView=attachment.content;
YYImage?*image=?(YYImage?*)imageView.image;
NSLog(@"獲取到圖片:%@",image);
}
NSArray?*attachmentRanges=textView.textLayout.attachmentRanges;
for?(NSValue?*range?in?attachmentRanges)
{
NSRanger=?[range?rangeValue];
NSLog(@"資源所在位置:%ld?長度:?%ld",r.location,r.length);
}
}
-?(void)didReceiveMemoryWarning?{
[super?didReceiveMemoryWarning];
//?Dispose?of?any?resources?that?can?be?recreated.
}
/*
#pragma?mark?-?Navigation
//?In?a?storyboard-based?application,?you?will?often?want?to?do?a?little?preparation?before?navigation
-?(void)prepareForSegue:(UIStoryboardSegue?*)segue?sender:(id)sender?{
//?Get?the?new?view?controller?using?[segue?destinationViewController].
//?Pass?the?selected?object?to?the?new?view?controller.
}
*/
@end
以上代碼加上注釋應(yīng)該很容易理解就不多講了? 注意 \n 這個換行符的使用
看效果圖:
(可編輯的文本+圖片 有的app需要編輯文章功能 用這個就個可以大體實(shí)現(xiàn)了赛蔫,圖片和文本都已經(jīng)獲取到了 到時后對應(yīng)傳到服務(wù)器,之前沒用YYTextview也實(shí)現(xiàn)過這種功能摊沉,效果比較差矗钟,用這個實(shí)現(xiàn)恳蹲,相當(dāng)完美,必須給YYText作者點(diǎn)個贊)
上一篇博客記錄了一個圖文編輯器的功能(YYTextview的使用)响禽,接下來記錄一下YYLabel的簡單使用徒爹,
其實(shí)他們的圖文并排的原理都是一樣的 都是NSMutableAttributedString來處理富文本
之前用TQRichTextView實(shí)現(xiàn)過emoji表情+文字 雖然性能還行,但是 計算文本高度是一個讓我非常頭疼的問題芋类,經(jīng)常容易算不準(zhǔn)隆嗅,表情的大小很難調(diào)整,今天YYLabel簡單了實(shí)現(xiàn)了一下他的emoji表情+文字的列表排布侯繁,個人感覺相當(dāng)好用 YYLabel提供計算文本的高度胖喳,性能也很好,有個異步渲染的機(jī)制贮竟,牛逼丽焊!
話不多說上代碼:
//
//??UserVC.h
//??YYTextDemo
//
//??Created?by?linpeng?on?16/3/13.
//??Copyright???2016年?ibireme.?All?rights?reserved.
//
#import
@interface?UserVC?:?UIViewController
@end
//
//??UserVC.m
//??YYTextDemo
//
//??Created?by?linpeng?on?16/3/13.
//??Copyright???2016年?ibireme.?All?rights?reserved.
//
#import?"UserVC.h"
#import?"YYText.h"
#import?"UIView+YYAdd.h"
#import?"YYImage.h"
#import?"NSBundle+YYAdd.h"
#import?"NSString+YYAdd.h"
@interface?CellModel?:?NSObject
@property?(nonatomic,strong)?YYTextLayout?*textLayout;
@property?(nonatomic)?CGFloat?cellHeight;
@end
@implementation?CellModel
@end
//=====================================分割線=========================================
@interface?UserVCCell?:?UITableViewCell
@property?(nonatomic,strong)?CellModel?*data;
@property?(nonatomic,?strong)?YYLabel?*contentLabel;
@end
@implementation?UserVCCell
#define?kWidth???280
#define?kLabelMarginTop??10
-(instancetype)initWithStyle:(UITableViewCellStyle)style?reuseIdentifier:(NSString?*)reuseIdentifier
{
self=?[super?initWithStyle:style?reuseIdentifier:reuseIdentifier];
if?(self)
{
[self?addSubview:self.contentLabel];
}
return?self;
}
-(void)setData:(CellModel?*)data
{
_data=data;
YYTextLayout?*layout=data.textLayout;
self.contentLabel.textLayout=layout;
self.contentLabel.size=layout.textBoundingSize;
}
-(YYLabel?*)contentLabel
{
if?(_contentLabel==?nil)?{
_contentLabel=?[[YYLabel?alloc]?initWithFrame:CGRectMake((kScreenWidth?-?kWidth)/2.0,?kLabelMarginTop,?0,?0)];
_contentLabel.userInteractionEnabled=YES;
_contentLabel.numberOfLines=0;
UIFont?*font=?[UIFont?systemFontOfSize:16];
_contentLabel.font=font;
_contentLabel.displaysAsynchronously=YES;?///?enable?async?display
_contentLabel.textVerticalAlignment=YYTextVerticalAlignmentTop;
[_contentLabel?setBackgroundColor:[[UIColor?grayColor]?colorWithAlphaComponent:0.2]];
}
return?_contentLabel;
}
@end
//=====================================分割線=========================================
@interface?UserVC?()
@property?(nonatomic,strong)?NSMutableArray?*dataList;
@end
@implementation?UserVC
NSMutableAttributedString?*attributeText;
-?(void)viewDidLoad?{
[super?viewDidLoad];
[self.view?setBackgroundColor:[UIColor?whiteColor]];
UITableView?*tableView=?[[UITableView?alloc]?initWithFrame:self.view.bounds];
[tableView?registerClass:[UserVCCell?class]?forCellReuseIdentifier:@"tableCell"];
tableView.delegate=self;
tableView.dataSource=self;
[self.view?addSubview:tableView];
dispatch_async(dispatch_get_main_queue(),?^{
NSMutableArray?*arrays=?[NSMutableArray?new];
for?(inti=0;?i<100;?i++)
{
NSMutableAttributedString?*text=?[NSMutableAttributedString?new];
NSString?*title11=?@"開始?";
[text?appendAttributedString:[[NSAttributedString?alloc]?initWithString:title11?attributes:nil]];
UIFont?*font=?[UIFont?systemFontOfSize:16];
NSArray?*names=?@[@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",@"001",@"001",@"022",@"022",@"022",@"022",@"022",@"022",@"022",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"022",@"022",@"022",@"022",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",?@"019",@"056",@"085",@"001",?@"022",@"001",@"001",@"022",@"022",@"022",@"022",@"022",@"022",@"022",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"001",@"022",@"022",@"022",@"022"];
for?(intj=0;j
{
NSString?*name=names[j];
NSString?*path=?[[NSBundle?mainBundle]?pathForScaledResource:name?ofType:@"png"?inDirectory:@"EmoticonQQ.bundle"];
NSData?*data=?[NSData?dataWithContentsOfFile:path];
YYImage?*image=?[YYImage?imageWithData:data?scale:2];//修改表情大小
image.preloadAllAnimatedImageFrames=YES;
YYAnimatedImageView?*imageView=?[[YYAnimatedImageView?alloc]?initWithImage:image];
NSMutableAttributedString?*attachText=?[NSMutableAttributedString?yy_attachmentStringWithContent:imageView?contentMode:UIViewContentModeCenter?attachmentSize:imageView.size?alignToFont:font?alignment:YYTextVerticalAlignmentCenter];
[text?appendAttributedString:attachText];
if(arc4random()%5==0)
{
[text?appendAttributedString:[[NSAttributedString?alloc]?initWithString:@"這是亂七八糟的文字"?attributes:nil]];
}
}
[text?appendAttributedString:[[NSAttributedString?alloc]?initWithString:@"結(jié)束"?attributes:nil]];
YYTextContainer?*container=?[YYTextContainer?containerWithSize:CGSizeMake(kWidth,?MAXFLOAT)];
YYTextLayout?*textLayout=?[YYTextLayout?layoutWithContainer:container?text:text];
CellModel?*model=?[[CellModel?alloc]?init];
model.textLayout=textLayout;
model.cellHeight=textLayout.textBoundingSize.height;
[arrays?addObject:model];
}
self.dataList=arrays;
//更新UI
dispatch_async(dispatch_get_main_queue(),?^{
[tableView?reloadData];
});
});
}
-(UITableViewCell?*)tableView:(UITableView?*)tableView?cellForRowAtIndexPath:(NSIndexPath?*)indexPath
{
static?NSString?*cellID=?@"tableCell";
UserVCCell?*cell=?[tableView?dequeueReusableCellWithIdentifier:cellID];
if?(!cell)
{
cell=?[[UserVCCell?alloc]?initWithStyle:UITableViewCellStyleDefault?reuseIdentifier:cellID];
}
CellModel?*model=self.dataList[indexPath.row];
cell.data=model;
return?cell;
}
-(NSInteger)tableView:(UITableView?*)tableView?numberOfRowsInSection:(NSInteger)section
{
return?self.dataList.count;
}
-(CGFloat)tableView:(UITableView?*)tableView?heightForRowAtIndexPath:(NSIndexPath?*)indexPath
{
CellModel?*model=self.dataList[indexPath.row];
CGFloatheight=model.cellHeight;
return?height?+?2*kLabelMarginTop;
}
-?(void)didReceiveMemoryWarning?{
[super?didReceiveMemoryWarning];
//?Dispose?of?any?resources?that?can?be?recreated.
}
/*
#pragma?mark?-?Navigation
//?In?a?storyboard-based?application,?you?will?often?want?to?do?a?little?preparation?before?navigation
-?(void)prepareForSegue:(UIStoryboardSegue?*)segue?sender:(id)sender?{
//?Get?the?new?view?controller?using?[segue?destinationViewController].
//?Pass?the?selected?object?to?the?new?view?controller.
}
*/
@end
看效果??我模擬了100條數(shù)據(jù) 所以數(shù)據(jù)那用了GCD 然后更新UI
ps:正則過濾表情生成NSMutableAttributedString
正常我們使用的時候是通過一串字符串(包含表情的占位符)來對應(yīng)顯示
例如:
[嘻嘻][嘻嘻][嘻嘻]我們[喜歡][喜歡][喜歡]你們[錢][錢][錢]這樣[可愛][可愛][可愛]我的小時候[可愛][可愛][可愛][可愛][可愛]
以下利用正則表達(dá)式來過濾各個表情的位置
-(NSMutableAttributedString *)processCommentContent:(NSString *)text
{
//轉(zhuǎn)成可變屬性字符串
NSMutableAttributedString?*mAttributedString=?[[NSMutableAttributedString?alloc]init];
NSMutableParagraphStyle?*paragraphStyle=?[[NSMutableParagraphStyle?alloc]?init];
[paragraphStyle?setLineSpacing:4];//調(diào)整行間距
[paragraphStyle?setParagraphSpacing:4];//調(diào)整行間距
NSDictionary?*attri=?[NSDictionary?dictionaryWithObjects:@[kCurrentLabelFont,[UIConstants?getWordColorC2],paragraphStyle]?forKeys:@[NSFontAttributeName,NSForegroundColorAttributeName,NSParagraphStyleAttributeName]];
[mAttributedString?appendAttributedString:[[NSAttributedString?alloc]?initWithString:text?attributes:attri]];
//創(chuàng)建匹配正則表達(dá)式的類型描述模板
NSString?*pattern=?@"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]";
//創(chuàng)建匹配對象
NSError?*?error;
NSRegularExpression?*regularExpression=?[NSRegularExpression?regularExpressionWithPattern:pattern?options:NSRegularExpressionCaseInsensitive?error:&error];
//判斷
if?(!regularExpression)//如果匹配規(guī)則對象為nil
{
NSLog(@"正則創(chuàng)建失敗坝锰!");
NSLog(@"error=?%@",[error?localizedDescription]);
return?nil;
}
else
{
NSArray?*resultArray=?[regularExpression?matchesInString:mAttributedString.string?options:NSMatchingReportCompletion?range:NSMakeRange(0,?mAttributedString.string.length)];
//開始遍歷?逆序遍歷
for?(NSIntegeri=resultArray.count?-?1;?i>=?0;?i?--)
{
//獲取檢查結(jié)果粹懒,里面有range
NSTextCheckingResult?*result=resultArray[i];
//根據(jù)range獲取字符串
NSString?*rangeString=?[mAttributedString.string?substringWithRange:result.range];
NSString?*imageName=??[[KSFaceManager?shareManager]?reflectFaceIDWithFace:rangeString];
if?(imageName)
{
//獲取圖片
UIImage?*image=?[self?getImageWithRangeString:imageName];//這是個自定義的方法
if?(image?!=?nil)
{
UIImageView?*imageView=?[[UIImageView?alloc]?initWithImage:image];
imageView.width=23;
imageView.height=23;
NSMutableAttributedString?*attachText=?[NSMutableAttributedString?yy_attachmentStringWithContent:imageView?contentMode:UIViewContentModeCenter?attachmentSize:imageView.size?alignToFont:[UIFont?systemFontOfSize:16]?alignment:YYTextVerticalAlignmentCenter];
//開始替換
[mAttributedString?replaceCharactersInRange:result.range?withAttributedString:attachText];
}
}
}
}
return?mAttributedString;
}
//根據(jù)rangeString獲取plist中的圖片
-(UIImage?*)getImageWithRangeString:(NSString?*)rangeString
{
return?[UIImage?imageNamed:rangeString];
}