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

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

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

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

XWTagView(高性能標(biāo)簽)

XWTagMaker(標(biāo)簽外觀配置)

#import#importtypedef enum : NSUInteger {

XWTagAlignmentLeft = 0,

XWTagAlignmentCenter = 1,

XWTagAlignmentRight = 2,

} XWTagAlignment;

@interfaceXWTagMaker : NSObject

//標(biāo)簽邊框

@property (nonatomic) CGFloat strokeWidth;

//標(biāo)簽邊框顏色

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

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

@property (nonatomic) CGLineJoin lineJoin;

//標(biāo)簽內(nèi)容內(nèi)邊距

@property (nonatomic) UIEdgeInsets insets;

//標(biāo)簽圓角

@property (nonatomic) CGFloat cornerRadius;

//標(biāo)簽填充顏色

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

//字體大小

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

//字體顏色

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

//標(biāo)簽上下間距

@property (nonatomic,assign) CGFloat lineSpace;

//標(biāo)簽的最大寬度-》以便計(jì)算高度

@property (nonatomic,assign) CGFloat maxWidth;

//對齊方式

@property (nonatomic,assign) XWTagAlignment tagAlignment;

@end

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

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標(biāo)簽所需樣式

@param tags 字符串?dāng)?shù)組

@param maskBlock 初始化標(biāo)簽樣式

@return 標(biāo)簽所需的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];

//設(shè)置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;

}

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

@interfaceNSMutableAttributedString (XWTagView)

//當(dāng)前標(biāo)簽富文本的高度

@property (nonatomic,assign) CGFloat tagHeight;

@end

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

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

NSArray *tags = @[

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

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

];

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就可以配置標(biāo)簽樣式了箍邮,如果您是比較復(fù)雜的列表的話茉帅,這樣一個label實(shí)現(xiàn)的標(biāo)簽性能完全不用擔(dān)心,如果您是個追求性能的人锭弊,可以開啟YYLabel的異步繪制displaysAsynchronously堪澎。效果圖如下

tagLeft.png

tagRight.png

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

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

style.lineSpacing =? maker.lineSpace;

switch(maker.tagAlignment) {

caseXWTagAlignmentLeft:

style.alignment = NSTextAlignmentLeft;

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

break;

caseXWTagAlignmentCenter:

style.alignment = NSTextAlignmentCenter;

break;

caseXWTagAlignmentRight:

style.alignment = NSTextAlignmentRight;

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

break;

default:

break;

}

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末就轧,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子田度,更是在濱河造成了極大的恐慌妒御,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镇饺,死亡現(xiàn)場離奇詭異乎莉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門惋啃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哼鬓,“玉大人,你說我怎么就攤上這事边灭∫煜#” “怎么了?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵绒瘦,是天一觀的道長称簿。 經(jīng)常有香客問我,道長惰帽,這世上最難降的妖魔是什么憨降? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮该酗,結(jié)果婚禮上授药,老公的妹妹穿的比我還像新娘。我一直安慰自己呜魄,他們只是感情好悔叽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著耕赘,像睡著了一般骄蝇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上操骡,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天九火,我揣著相機(jī)與錄音,去河邊找鬼册招。 笑死岔激,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的是掰。 我是一名探鬼主播虑鼎,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼键痛!你這毒婦竟也來了炫彩?” 一聲冷哼從身側(cè)響起昌简,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤狠半,失蹤者是張志新(化名)和其女友劉穎系宜,沒想到半個月后齿拂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡飒责,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年膳犹,在試婚紗的時候發(fā)現(xiàn)自己被綠了束亏。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叔磷,死狀恐怖拢驾,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情改基,我是刑警寧澤繁疤,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站秕狰,受9級特大地震影響嵌洼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜封恰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望褐啡。 院中可真熱鬧诺舔,春花似錦、人聲如沸备畦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽懂盐。三九已至褥赊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間莉恼,已是汗流浹背拌喉。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留俐银,地道東北人尿背。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像捶惜,于是被迫代替她去往敵國和親田藐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容