iOS簡單高效能標籤TagView(巧用YYLabel)

weixin_34019929發表於2017-11-02

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

7877747-427a93ef8fa03af7.jpg

很多人都可以自己實現(網上別人寫的也很多,但是別人寫的總有不滿足自己需求的點),實現的方法也很多種,比如動態新增view,使用UICollectionView等等。這種實現方法不是不好,但是當列表比較複雜,資料比較多的時候,可曾想過效能會怎麼樣呢?

在一次深入瞭解富文字的時候,突發其想,好像富文字能達到這種效果,也就是一個label就可以實現這種標籤的效果了,效果效能就不用多說了,再加上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;

/**

快速建立tag標籤所需樣式

@param tags 字串陣列

@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;

}

細心的同學會發現要怎麼知道他的高度?(當然如果您用的是自動佈局可以不用管這個屬性,畢竟label自動佈局會自動自適應)從上面程式碼可以看出來,最後返回的是富文字NSMutableAttributedString,為了更加方便,我便為NSMutableAttributedString擴充套件了個高度屬性tagHeight(當前標籤富文字的高度以便外部獲取使用和快取),具體看以下程式碼

@interfaceNSMutableAttributedString (XWTagView)

//當前標籤富文字的高度

@property (nonatomic,assign) CGFloat tagHeight;

@end

看起來很簡單,也很容易理解(就是把標籤陣列變成一個富文字已達到標籤的效果),接下來就看看怎麼用吧

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實現的標籤效能完全不用擔心,如果您是個追求效能的人,可以開啟YYLabel的非同步繪製displaysAsynchronously。效果圖如下

7877747-48b6e296cf1a7cca.jpg

tagLeft.png

7877747-b7d850adb8bfaa27.jpg

tagRight.png

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

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是與尾部的距離,利用好這一點可以很好的解決問題

相關文章