iOS簡單高性能標簽TagView(巧用YYLabel)

我相信很多人在開發(fā)者都有這樣的需求,標簽展示(如下圖)

很多人都可以自己實現(xiàn)(網(wǎng)上別人寫的也很多,但是別人寫的總有不滿足自己需求的點),實現(xiàn)的方法也很多種,比如動態(tài)添加view,使用UICollectionView等等。這種實現(xiàn)方法不是不好,但是當列表比較復雜,數(shù)據(jù)比較多的時候,可曾想過性能會怎么樣呢?

在一次深入了解富文本的時候,突發(fā)其想,好像富文本能達到這種效果,也就是一個label就可以實現(xiàn)這種標簽的效果了,效果性能就不用多說了,再加上YYLabel的異步繪制,真是錦上添花啊。

XWTagView(高性能標簽)

XWTagMaker(標簽外觀配置)

#import#importtypedef enum : NSUInteger {

XWTagAlignmentLeft = 0,

XWTagAlignmentCenter = 1,

XWTagAlignmentRight = 2,

} XWTagAlignment;

@interfaceXWTagMaker : NSObject

//標簽邊框

@property (nonatomic) CGFloat strokeWidth;

//標簽邊框顏色

@property (nullable, nonatomic, strong) UIColor *strokeColor;

//路徑的連接點形狀,] kCGLineJoinMiter(默認全部連接),kCGLineJoinRound(圓形連接),kCGLineJoinBevel(斜角連接)

@property (nonatomic) CGLineJoin lineJoin;

//標簽內容內邊距

@property (nonatomic) UIEdgeInsets insets;

//標簽圓角

@property (nonatomic) CGFloat cornerRadius;

//標簽填充顏色

@property (nullable, nonatomic, strong) UIColor *fillColor;

//字體大小

@property (nonatomic,strong) UIFont * _Nullable font;

//字體顏色

@property (nonatomic,strong) UIColor * _Nonnull textColor;

//標簽上下間距

@property (nonatomic,assign) CGFloat lineSpace;

//標簽的最大寬度-》以便計算高度

@property (nonatomic,assign) CGFloat maxWidth;

//對齊方式

@property (nonatomic,assign) XWTagAlignment tagAlignment;

@end

以上就是標簽外觀的一些屬性,注釋得很清楚,包含了對齊方式,每個屬性都有默認值,maxWidth這個屬性是必須非空的以便計算高度和換行(默認值是屏幕寬度)

XWTagView(繼承自YYLabel)

XWTagView.h

#import"YYText.h"

#import"XWTagMaker.h"

#import"NSMutableAttributedString+XWTagView.h"

@interfaceXWTagView : YYLabel

/**

*NSMutableAttributedString

*/

@property (nonatomic,strong) NSMutableAttributedString * tagAttr;

/**

快速創(chuàng)建tag標簽所需樣式

@param tags 字符串數(shù)組

@param maskBlock 初始化標簽樣式

@return 標簽所需的NSMutableAttributedString

*/

+(NSMutableAttributedString *)xw_makeTagView:(NSArray *)tags tagMaker:(void(^)(XWTagMaker *))maskBlock;

@end

XWTagView.m主要代碼

+(NSMutableAttributedString *)xw_makeTagView:(NSArray *)tags? tagMaker:(void(^)(XWTagMaker *))maskBlock{

NSMutableAttributedString *text = [NSMutableAttributedString new];

NSInteger height = 0;

XWTagMaker *maker = [[XWTagMaker alloc] init];

if(maskBlock) {

maskBlock(maker);

}

for(inti = 0; i < tags.count; i++) {

NSString *tag = tags[i];

NSMutableAttributedString *tagText = [[NSMutableAttributedString alloc] initWithString:tag];

[tagText yy_insertString:@"? "atIndex:0];

[tagText yy_appendString:@"? "];

tagText.yy_font = maker.font;

tagText.yy_color = maker.textColor;

[tagText yy_setTextBinding:[YYTextBinding bindingWithDeleteConfirm:NO] range:tagText.yy_rangeOfAll];

//設置item外觀樣式

[tagText yy_setTextBackgroundBorder:[self creatTextBoard:maker] range:[tagText.string rangeOfString:tag]];

[text appendAttributedString:tagText];

text.yy_lineSpacing = maker.lineSpace;

text.yy_lineBreakMode = NSLineBreakByWordWrapping;

YYTextContainer? *tagContarer = [YYTextContainer new];

tagContarer.size = CGSizeMake(maker.tagAlignment == XWTagAlignmentRight ? (maker.maxWidth - fabs(maker.insets.right)) : maker.maxWidth ,CGFLOAT_MAX);

YYTextLayout *tagLayout = [YYTextLayout layoutWithContainer:tagContarer text:text];

if(tagLayout.textBoundingSize.height > height) {

if(i != 0) {

[text yy_insertString:@"\n"atIndex:text.length - tagText.length];

}

height = tagLayout.textBoundingSize.height;

}

}

text.tagHeight = height + maker.lineSpace;

[text addAttribute:NSParagraphStyleAttributeName value:[self creatTextStyle:maker]

range:NSMakeRange(0, text.length)];

returntext;

}

細心的同學會發(fā)現(xiàn)要怎么知道他的高度?(當然如果您用的是自動布局可以不用管這個屬性,畢竟label自動布局會自動自適應)從上面代碼可以看出來,最后返回的是富文本NSMutableAttributedString,為了更加方便,我便為NSMutableAttributedString擴展了個高度屬性tagHeight(當前標簽富文本的高度以便外部獲取使用和緩存),具體看以下代碼

@interfaceNSMutableAttributedString (XWTagView)

//當前標簽富文本的高度

@property (nonatomic,assign) CGFloat tagHeight;

@end

看起來很簡單,也很容易理解(就是把標簽數(shù)組變成一個富文本已達到標簽的效果),接下來就看看怎么用吧

XWTagView *tagView = [[XWTagView alloc] initWithFrame:CGRectMake(10, 100, self.view.bounds.size.width-20, 50)];

NSArray *tags = @[

@"標簽tag1",@"表面",@"哈哈哈",@"測試測試",@"不不不不",@"無敵啊",@"標簽",@"這樣喊得好嗎",

@"哈哈哈",@"嘻嘻嘻",@"呵呵呵",@"標簽",@"表面兄弟",@"你好啊",@"不想你了哦",@"不要這樣子啦"

];

NSMutableAttributedString *attr = [XWTagView xw_makeTagView:tags tagMaker:^(XWTagMaker *make){

make.strokeColor = [UIColor redColor];

make.fillColor = [UIColor clearColor];

make.strokeWidth = 1;

make.cornerRadius = 100;

make.insets =? UIEdgeInsetsMake(-2, -6, -2, -6);

make.font = [UIFont systemFontOfSize:16];

make.textColor = [UIColor blackColor];

make.lineSpace = 10;

make.maxWidth = [UIScreen mainScreen].bounds.size.width - 20;

make.tagAlignment = XWTagAlignmentLeft;

}];

tagView.tagAttr = attr;

tagView.frame = CGRectMake(10, 100, self.view.bounds.size.width - 20, attr.tagHeight);

[self.view addSubview:tagView];

看起來是不是很簡單,一個make就可以配置標簽樣式了,如果您是比較復雜的列表的話,這樣一個label實現(xiàn)的標簽性能完全不用擔心,如果您是個追求性能的人,可以開啟YYLabel的異步繪制displaysAsynchronously。效果圖如下

tagLeft.png

tagRight.png

當我以為大功告成的時候,最后還是讓我發(fā)現(xiàn)了個問題,從上面代碼可以看出標簽的的左右間隔是用空字符串隔開的(這是一個缺陷,有比較好的解決方法的可以聯(lián)系我),說到這細心的同學應該可以猜到是什么問題了,你們可曾注意過當label右對齊的時候,最右邊的空格或者空字符串是不起作用的,最終想到了個解決辦法,可能不是最好的解決方案,但是足以解決出現(xiàn)的問題,詳細的見如下代碼

NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];

style.lineSpacing =? maker.lineSpace;

switch(maker.tagAlignment) {

caseXWTagAlignmentLeft:

style.alignment = NSTextAlignmentLeft;

//style.firstLineHeadIndent = fabs(maker.insets.left) ;//設置與首部的距離

break;

caseXWTagAlignmentCenter:

style.alignment = NSTextAlignmentCenter;

break;

caseXWTagAlignmentRight:

style.alignment = NSTextAlignmentRight;

style.tailIndent = maker.insets.right - 2; //設置與尾部的距離

break;

default:

break;

}

熟悉富文本的同學都知道tailIndent是與尾部的距離,利用好這一點可以很好的解決問題

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容