亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS利用Label實現的簡單高性能標簽TagView

2020-07-26 02:29:11
字體:
來源:轉載
供稿:網友

前言

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


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

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

XWTagView(高性能標簽)

優勢:

  • 支持自定義標簽外觀,上下距離,左右距離,對齊方式;
  • 異步繪制性能得到很大提升。

XWTagMaker(標簽外觀配置)

#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>typedef enum : NSUInteger { XWTagAlignmentLeft = 0, XWTagAlignmentCenter = 1, XWTagAlignmentRight = 2,} XWTagAlignment;@interface XWTagMaker : 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 space;//標簽的最大寬度-》以便計算高度@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"@interface XWTagView : YYLabel/** *NSMutableAttributedString */@property (nonatomic,strong) NSMutableAttributedString * tagAttr;@end

XWTagView.m主要代碼

XWTagView的內部實現很簡單,只是簡單的富文本賦值

-(instancetype)init{ if (self = [super init]) {  [self initTagView]; } return self;}-(instancetype)initWithFrame:(CGRect)frame{ if (self = [super initWithFrame:frame]) {  [self initTagView]; } return self;}-(void)initTagView{ self.numberOfLines = 0; self.lineBreakMode = NSLineBreakByWordWrapping; self.displaysAsynchronously = YES;}-(void)setTagAttr:(NSMutableAttributedString *)tagAttr{ _tagAttr = tagAttr; [self initTagView]; self.attributedText = _tagAttr;}

NSMutableAttributedString +XWTagView的核心代碼

1.tip:創建標簽的時候在子線程體驗更好(生成富文本比較耗時)

#import <Foundation/Foundation.h>#import <UIKit/UIKit.h>#import "XWTagMaker.h"@interface NSMutableAttributedString (XWTagView)//當前標簽富文本的高度@property (nonatomic,assign) CGFloat tagHeight;/** 快速創建tag標簽所需樣式 @param tags 字符串數組 @param maskBlock 初始化標簽樣式 @return 標簽所需的NSMutableAttributedString */+(NSMutableAttributedString *)xw_makeTagAttributedString:(NSArray<NSString *> *)tags tagMaker:(void (^)(XWTagMaker *))maskBlock;@end
+(NSMutableAttributedString *)xw_makeTagAttributedString:(NSArray<NSString *> *)tags tagMaker:(void (^)(XWTagMaker *))maskBlock{ NSMutableAttributedString *text = [NSMutableAttributedString new]; NSInteger height = 0; XWTagMaker *maker = [[XWTagMaker alloc] init]; if (maskBlock) {  maskBlock(maker); } for (int i = 0; i < tags.count; i++) {  NSString *tag = tags[i];  NSMutableAttributedString *tagText = [[NSMutableAttributedString alloc] init];  //標簽左內邊距  [tagText appendAttributedString:[self creatEmptyAttributeString:fabs(maker.insets.left)]];  //標簽內容  [tagText yy_appendString:tag];  //標簽右內邊距  [tagText appendAttributedString:[self creatEmptyAttributeString:fabs(maker.insets.right)]];  //設置外觀  [self beautifyAttributedStringWithText:tagText ranges:NSMakeRange(0, tagText.length) maker:maker];  //左右間距  [tagText appendAttributedString:[self creatEmptyAttributeString:maker.space]];  //行間距等設置  [text appendAttributedString:tagText];  text.yy_lineSpacing = maker.lineSpace;  text.yy_lineBreakMode = NSLineBreakByWordWrapping;  //高度計算(超最大范圍加換行符手動換行)  YYTextContainer *tagContarer = [YYTextContainer new];  tagContarer.size = CGSizeMake(maker.maxWidth - 3,CGFLOAT_MAX);  YYTextLayout *tagLayout = [YYTextLayout layoutWithContainer:tagContarer text:text];  if (tagLayout.textBoundingSize.height > height) {   if (height != 0) {    [text yy_insertString:@"/n" atIndex:text.length - tagText.length];       }   tagLayout = [YYTextLayout layoutWithContainer:tagContarer text:text];   height = tagLayout.textBoundingSize.height;  } }  //高度記錄(富文本已擴展高度屬性) text.tagHeight = height + maker.lineSpace + fabs(maker.insets.top) + fabs(maker.insets.bottom) ; //對齊方向設置(頭尾自動縮進1.5) [text addAttribute:NSParagraphStyleAttributeName value:[self creatTextStyle:maker]     range:NSMakeRange(0, text.length)]; return text;}+(void) beautifyAttributedStringWithText:(NSMutableAttributedString * )tagText ranges:(NSRange)range maker:(XWTagMaker *)maker{ //標簽字體顏色設置 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:range]; }/** 外觀樣式 @param maker tag外觀配置 @return 返回YYTextBorder */+(YYTextBorder *)creatTextBoard:(XWTagMaker *)maker{ YYTextBorder *border = [YYTextBorder new]; border.strokeWidth = maker.strokeWidth; border.strokeColor = maker.strokeColor; border.fillColor = maker.fillColor; border.cornerRadius = maker.cornerRadius; // a huge value border.lineJoin = maker.lineJoin; border.insets = UIEdgeInsetsMake(maker.insets.top, 0, maker.insets.bottom, 0); return border;}+(NSMutableAttributedString *)creatEmptyAttributeString:(CGFloat)width{ NSMutableAttributedString *spaceText = [NSMutableAttributedString yy_attachmentStringWithContent:[[UIImage alloc]init] contentMode:UIViewContentModeScaleToFill attachmentSize:CGSizeMake(width, 1) alignToFont:[UIFont systemFontOfSize:0] alignment:YYTextVerticalAlignmentCenter]; return spaceText; }+(NSMutableParagraphStyle *)creatTextStyle:(XWTagMaker *)maker{ NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; style.lineSpacing = maker.lineSpace; style.firstLineHeadIndent = 1.5; style.headIndent = 1.5 ;//設置與首部的距離 style.tailIndent = maker.tagAlignment == NSTextAlignmentRight ? maker.maxWidth - fabs(maker.insets.right) : maker.maxWidth - 1.5; //設置與尾部的距離 switch (maker.tagAlignment) {  case XWTagAlignmentLeft:   style.alignment = NSTextAlignmentLeft;   break;  case XWTagAlignmentCenter:   style.alignment = NSTextAlignmentCenter;   break;  case XWTagAlignmentRight:   style.alignment = NSTextAlignmentRight;   break;  default:   break; } return style;}

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

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

XWTagView *tagView = [[XWTagView alloc] initWithFrame:CGRectMake(10, 100, self.view.bounds.size.width-20, 50)]; NSArray<NSString *> *tags = @[         @"標簽tag1",@"表面",@"哈哈哈",@"測試測試",@"不不不不",@"無敵啊",@"標簽",@"這樣喊得好嗎",         @"哈哈哈",@"嘻嘻嘻",@"呵呵呵",@"標簽",@"表面兄弟",@"你好啊",@"不想你了哦",@"不要這樣子啦"         ]; NSMutableAttributedString *attr = [NSMutableAttributedString xw_makeTagAttributedString: 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.space = 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(在iPhone4s上有明顯效果)。

效果圖如下



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

 NSMutableParagraphStyle *style = [[NSParagraphStyle defaultParagraphStyle] mutableCopy]; style.lineSpacing = maker.lineSpace; style.firstLineHeadIndent = 1.5; style.headIndent = 1.5 ;//設置與首部的距離 style.tailIndent = maker.tagAlignment == NSTextAlignmentRight ? maker.maxWidth - fabs(maker.insets.right) : maker.maxWidth - 1.5; //設置與尾部的距離 switch (maker.tagAlignment) {  case XWTagAlignmentLeft:   style.alignment = NSTextAlignmentLeft;   break;  case XWTagAlignmentCenter:   style.alignment = NSTextAlignmentCenter;   break;  case XWTagAlignmentRight:   style.alignment = NSTextAlignmentRight;   break;  default:   break; }

熟悉富文本的同學都知道tailIndent是與尾部的距離,利用好這一點可以很好的解決問題,后續會加上點擊事件。

總結

富文本很強大,能做的不只只這些,很多黑科技等著你去發現哦,當然如果您覺得我寫的不錯,希望您點個贊。

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美亚洲在线视频| 国产美女精品视频免费观看| 91精品国产高清久久久久久| 蜜臀久久99精品久久久无需会员| 欧美洲成人男女午夜视频| 国产精品电影网| 国产精品高清在线观看| 日韩美女视频免费看| 欧美亚洲日本黄色| 国产一区深夜福利| 日韩一区视频在线| 亚洲欧美日韩久久久久久| 久久久www成人免费精品| 久久久噜噜噜久久久| 欧美一区二区影院| 国产丝袜一区二区三区| 在线日韩中文字幕| 亚洲第一区第一页| 欧美xxxx做受欧美| 国产精品久久久久久久久久久久久久| 91精品综合久久久久久五月天| 国内伊人久久久久久网站视频| 亚洲最大福利视频| 欧美黑人一级爽快片淫片高清| 精品国产一区二区三区四区在线观看| 国产精品揄拍一区二区| 激情av一区二区| 成人在线小视频| 成人免费直播live| 亚洲老头同性xxxxx| 亚洲精品久久久久久久久久久| 日韩欧美在线一区| 国产精品久久久久久久久免费| 国内精品400部情侣激情| 欧美日韩福利视频| 欧美亚洲伦理www| 狠狠综合久久av一区二区小说| 91成人国产在线观看| 国产aaa精品| 久久久久久久久久久免费精品| 日韩动漫免费观看电视剧高清| 精品亚洲永久免费精品| 91精品国产高清自在线看超| 九九热精品视频国产| 亚洲综合在线中文字幕| 亚洲最大av网站| 中文在线不卡视频| 国产精品美女久久久久久免费| 久久久久久国产精品三级玉女聊斋| 日韩在线欧美在线国产在线| 成人福利视频网| 久久69精品久久久久久国产越南| 国产精品福利网站| 国产91精品网站| 欧美日本亚洲视频| 欧美国产日韩xxxxx| 国产日韩视频在线观看| 九九综合九九综合| 午夜精品久久久久久99热软件| 国内精品视频在线| 日本不卡免费高清视频| 亚洲mm色国产网站| 国产视频久久久久久久| 亚洲男人天堂2023| 国产91免费看片| 精品久久久久久久久久| 欧美性感美女h网站在线观看免费| 日韩av中文在线| 91av视频在线| 日韩一区二区三区xxxx| 欧美成年人视频网站欧美| 日韩理论片久久| 青草青草久热精品视频在线观看| 久久久精品一区| 日韩美女视频免费在线观看| 九九热在线精品视频| 欧美成人免费视频| 日韩精品免费在线视频| 久久久久久久久国产精品| 久久国产精品免费视频| 国产免费一区视频观看免费| 超碰日本道色综合久久综合| 欧美激情精品久久久久久| 久久免费福利视频| 色99之美女主播在线视频| 国产成人精品免高潮在线观看| 国产日韩欧美电影在线观看| 成人激情春色网| 国产亚洲免费的视频看| 欧美性高潮床叫视频| 在线日韩欧美视频| 欧美另类暴力丝袜| 自拍偷拍亚洲欧美| 精品无人国产偷自产在线| 国产精品久久999| 国产精品美女av| 日韩欧美亚洲综合| 国产成人激情小视频| 久久五月天色综合| 精品欧美aⅴ在线网站| 久久精品国产96久久久香蕉| 欧美日韩在线免费| 国产日产欧美a一级在线| 亚洲精品视频网上网址在线观看| 欧美性猛交xxxx乱大交蜜桃| 国产自摸综合网| 欧美激情一级欧美精品| 欧美午夜激情视频| 日本道色综合久久影院| 国产一区视频在线播放| 欧美激情视频网站| 久久躁日日躁aaaaxxxx| 国产精品入口免费视| 国产亚洲在线播放| 亚洲夜晚福利在线观看| 精品久久久久国产| 亚洲xxx自由成熟| 精品亚洲一区二区三区在线观看| 精品久久久久久电影| 91精品国产精品| 亚洲精品狠狠操| 欧美亚洲在线视频| 日本成人精品在线| 欧美高清在线播放| 欧美在线精品免播放器视频| 精品国产拍在线观看| 国内精品在线一区| 日韩成人黄色av| 欧美亚洲日本黄色| 全亚洲最色的网站在线观看| 亚洲图片在区色| 欧美国产日韩精品| 欧美精品在线极品| 久久影院免费观看| 456国产精品| 国产精品女人网站| 午夜精品在线视频| 欧美在线免费视频| 全色精品综合影院| 精品久久久999| 91在线精品视频| 8050国产精品久久久久久| 欧美日韩第一视频| 操人视频在线观看欧美| 精品中文视频在线| 亚洲大胆人体视频| 精品中文字幕在线2019| 国产成人av在线| 欧美激情国产日韩精品一区18| 亚洲系列中文字幕| 欧美巨大黑人极品精男| 日韩在线小视频| 欧美性xxxxx| 国产精品精品视频一区二区三区| 成人在线精品视频| 久久久久久国产精品| 欧美一级片久久久久久久| 亚洲国产99精品国自产| 久久五月天色综合| 国产精品99一区| 日韩av在线导航| 福利一区视频在线观看| 91九色视频导航| 亚洲精品国产精品自产a区红杏吧|