iOSはLabelを利用して実現したシンプルで高性能タグTagView

11091 ワード

前言
多くの人が開発者にこのようなニーズがあると信じています。ラベルの展示(以下の図)

多くの人が自分で実現することができます。(ネットで他の人が書いていることも多いですが、他の人が書いているのはいつも自分の要求に満足していない点があります。)、実現する方法もたくさんあります。例えば、動的にviewを追加したり、UICcollection Viewを使ったりします。このような実現方法はよくないですが、リストが複雑で、データが多い時、性能はどうなるかと思ったことがあります。
リッチテキストを深く理解した時、ふと思いました。リッチテキストはこの効果を達成できるようです。つまり、labelはこのラベルの効果を実現できます。効果性能はもちろん、YYLabelの異歩を加えて、錦上に花を添えます。
XWTRA View(高性能ラベル)
利点:
  • は、カスタムラベルの外観、上下距離、左右距離、配置をサポートします。
  • 非同期描画性能が大幅に向上した。
  • XWTRAGMaker(ラベル外観設定)
    
    #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という属性は空ではなく、高さと改行を計算する必要があります。
    XWT agView(YLabelから継承)
    XWTRA View.h
    
    #import "YYText.h"
    #import "XWTagMaker.h"
    #import "NSMutableAttributedString+XWTagView.h"
    @interface XWTagView : YYLabel
    /**
     *NSMutableAttributedString
     */
    @property (nonatomic,strong) NSMutableAttributedString * tagAttr;
    @end
    XWTRA View.m主要コード
    XWTRA Viewの内部実現は簡単で、テキストの豊富なだけの価値があります。
    
    -(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;
    }
    NSMutable AttributedString+XWT agViewのコアコード
    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:@"
    " 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自動レイアウトは自動的に適応します。上のコードから分かります。最後に戻ったのはリッチテキストNSMutable AttributedStringです。NSMutable AttributedStringのために高度属性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];
    簡単に見えるのではないですが、一つのメークでタグの配置ができます。複雑なリストであれば、このようなラベルの性能は全く心配しなくてもいいです。もしあなたが性能を求める人なら、YYLabelの異歩を開いてdisplays Achronouslyを描きます。
    効果図は以下の通りです


    成功したと思ったら、最後にやはり問題を発見しました。上のコードからラベルの左右の間隔は空の文字列で区切られていることが分かります。(これは欠点です。比較的良い解決方法があれば、私に連絡してください。)この注意深い学生は何か問題があると推測できます。あなた達はlabelの右揃えに注意したことがあります。一番右のスペースや空の文字列は機能しません。最終的に解決策を思いつきました。一番いい解決策ではないかもしれませんが、問題を解決するには十分です。詳細は下記のコードを参照してください。
    
     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が尾部との距離であることを知っています。この点を利用すれば、問題をうまく解決できます。後でクリックします。
    締め括りをつける
    テキストが豊かで、できるのはこれらだけではなくて、たくさんの黒科学技術があなたを待っています。もちろん、私が書いたのがいいと思ったら、いいです。
    はい、以上はこの文章の全部の内容です。本文の内容は皆さんの学習や仕事に対して一定の参考学習価値を持っています。質問があれば、メッセージを残して交流してください。ありがとうございます。