This article is borrowed from the ptlCoder and modified briefly on this article. ## Background, suppose we need to implement the following requirements, as shown in the figure

First of all, I found a bug in the sample code of ** ptlCoder**, that is, if we modify the UI of KMTag in the delegate method, the 0 is not changed. I analyzed the reason that the tag value is set relatively small (I didn’t look for the problem carefully).

###

#import <UIKit/UIKit.h>@interface KMTag : UILabel - (void)setupWithText:(NSString*)text; // I added @property(nonatomic,assign)BOOL isSelected; @endCopy the code

First of all, it inherits UILabel and creates a new KMTag, and adds a method to set the frame based on the text, and a property to see if it’s clicked.

## Implementation file (omitted some code)

#import "KMTag.h"

@implementation KMTag

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if(self) { self.textAlignment = NSTextAlignmentCenter; Self. isSelected = NO; }return self;
}

- (void)setupWithText:(NSString*)text {
        
    CGSize size = [text sizeWithAttributes:@{NSFontAttributeName: font}];
    CGRect frame = self.frame;
    frame.size = CGSizeMake(size.width + 20, size.height + 10);    
    self.frame = frame;    
}
@end
Copy the code

The implementation file is also relatively simple, mainly according to the text to determine the frame, here the author increases the width of the frame by 20 and the height of the frame by 10, and initializes his click attribute to NO.

## Here is the declaration file for kmtagListView.h

#import <UIKit/UIKit.h>

@class KMTagListView;
@protocol KMTagListViewDelegate<NSObject>
- (void)ptl_TagListView:(KMTagListView*)tagListView didSelectTagViewAtIndex:(NSInteger)index selectContent:(NSString *)content ifSelected:(BOOL)selected;
@end

@interface KMTagListView : UIScrollView
@property (nonatomic, weak)id<KMTagListViewDelegate> delegate_;
- (void)setupSubViewsWithTitles:(NSArray *)titles;
@end
Copy the code

Here we declare a method to layout a label and a protocol to which the label is clicked.

### Implementation file (part)

- (void)setupAllSubViews {/// Set x and y spacing. CGFloat marginX = 20; CGFloat marginY = 20; __block CGFloat x = 0; __block CGFloat x = 0; __block CGFloat y = 10; [self.tags enumerateObjectsUsingBlock:^(KMTag *obj, NSUInteger idx, BOOL * _Nonnull stop) { CGFloat height = CGRectGetHeight(obj.frame);if(idx == 0) {// if (idx == 0) { x = marginX; }else{ x = CGRectGetMaxX([self.tags[idx - 1] frame]) + marginX; /// it is out of bounds, out of line feeds.if( x + CGRectGetWidth(obj.frame) + marginX > CGRectGetWidth(self.frame) ) { x = marginX; y += height; y += marginY; } } CGRect frame = obj.frame; frame.origin = CGPointMake(x, y); obj.frame = frame; }]; // If there is only one line, center itif(y == 10) { [self.tags enumerateObjectsUsingBlock:^(KMTag *obj, NSUInteger idx, BOOL * _Nonnull stop) {CGFloat height = CGRectGetHeight(obj.frame); y = CGRectGetHeight(self.frame) / 2-height / 2.0;if (idx == 0) {
                x = marginX;
            }else {
                x = CGRectGetMaxX([self.tags[idx - 1] frame]) + marginX;
            }
            CGRect frame = obj.frame;
            frame.origin = CGPointMake(x, y);
            obj.frame = frame;
            
        }];
        
    }
    
    CGFloat contentHeight = CGRectGetMaxY([self.tags.lastObject frame]) + 10;
    if (contentHeight < CGRectGetHeight(self.frame)) {
        contentHeight = 0;
    }
    
    self.contentSize = CGSizeMake(0, contentHeight);
}
Copy the code

After ###, you can use it happily in VC, VC code is as follows:

#pragma mark - KMTagListViewDelegate
-(void)ptl_TagListView:(KMTagListView *)tagListView didSelectTagViewAtIndex:(NSInteger)index selectContent:(NSString *)content ifSelected:(BOOL)selected
{
    NSLog(@"content: %@ index: %zd", content, index);
    KMTag *tag = tagListView.subviews[index-1000]; 
    if (tag.isSelected) {
        tag.layer.borderColor = [UIColor redColor].CGColor;
    }
    else{ tag.layer.borderColor = tag.textColor.CGColor; }}Copy the code

Finally, the code download address: portal