标签流水布局(TagsView) 一行显示不下的自动折行

项目中经常遇到很多标签排列的那种, 之前一直用HXTagsView, 但是一个很小的需求, 就动用UICollectionView甚至是第三方, 总觉得有点小题大做, 索性自己动手写一个, 先看下效果图


核心代码:

    CGFloat currentX = 10;
    CGFloat currentY = 44;
    CGFloat spaceX = 10;     // 左右的空隙
    CGFloat spaceY = 15;     // 上下的空隙
    CGFloat marginRL = 10;   // 文字距左右边框的间距
    CGFloat lineH = 25;
    for (int i = 0; i<self.keywords.count; i++) {
        
        NSString *keyword = self.keywords[i];
        if (keyword == nil) continue;
        if (![keyword isKindOfClass:NSString.class]) keyword = [keyword description];
        
        CGFloat width = [keyword sizeWithAttributes:@{NSFontAttributeName:kNormalFont(12)}].width + marginRL;
    
        UIButton *button = [[UIButton alloc] init];
        button.backgroundColor = [UIColor whiteColor];
        button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
        button.titleLabel.font = kNormalFont(12);
        [button setTitle:keyword forState:UIControlStateNormal];
        [button setTitleColor:kColor666666 forState:UIControlStateNormal];
        [button addTarget:self action:@selector(itemEvent:) forControlEvents:UIControlEventTouchUpInside];
        // 一行显示不下
        if (width > kDeviceWidth-20) {
            currentY += currentX == 10 ? 0:(lineH+spaceY); // 第一行已经有的话折行 否则就显示在第一行
            currentX = 10;
            button.frame = CGRectMake(currentX, currentY, kDeviceWidth-20, lineH);
            currentX = 10; //
            currentY += lineH+spaceY;
        }
         // 剩余的空间 能显示下
        else if (kDeviceWidth-currentX-25 > width) {
            button.frame = CGRectMake(currentX, currentY, width, lineH);
            currentX += width+spaceX;
        }
        // 剩余的空间 显示不下 需要折行显示(但是这一行还没显示满 故不更新currentY)
        else{
            currentY += lineH+spaceY;
            currentX = 10;
            button.frame = CGRectMake(currentX, currentY, width, lineH);
            currentX += width+spaceX;
        }
        
        [self addSubview:button];
    }
    self.frame = CGRectMake(0, 0, kDeviceWidth, currentY+lineH+10);

具体样式可以自己修改,核心还是布局计算那块

完整代码如下:

typedef void(^HistoryBlock)(NSString *keyword, NSInteger index);
@interface SearchHistoryView : UIView
@property (nonatomic, strong) NSMutableArray *keywords; // 只保留最新的十条记录
@property (nonatomic, copy) HistoryBlock handle;

/**  保存一条新的搜索记录*/
+ (BOOL)saveKeyword:(NSString *)keyword;
@end
实现:
@implementation SearchHistoryView

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self setUpSubviews];
    }
    return self;
}

- (void)reloadData{
    
    for (UIView *view in self.subviews) {
        [view removeFromSuperview];
    }
    
    [self setUpSubviews];
}

- (void)setUpSubviews{
    
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, kDeviceWidth-20, 44)];
    titleLabel.font = kNormalFont(14);
    titleLabel.text = @"最近搜索";
    titleLabel.textColor = kColor333333;
    
//    UIButton *clear = [[UIButton alloc] initWithFrame:CGRectMake(kDeviceWidth-50, 0, 40, 44)];
//    clear.hidden = self.keywords.count == 0;
//    [clear setImage:Image(@"icon_cache") forState:UIControlStateNormal];
//    [clear addTarget:self action:@selector(clearKeywords) forControlEvents:UIControlEventTouchUpInside];
//    [self addSubview:clear];
    [self addSubview:titleLabel];
    
    CGFloat currentX = 10;
    CGFloat currentY = 44;
    CGFloat spaceX = 10;     // 左右的空隙
    CGFloat spaceY = 15;     // 上下的空隙
    CGFloat marginRL = 10;   // 文字距左右边框的间距
    CGFloat lineH = 25;
    for (int i = 0; i<self.keywords.count; i++) {
        
        NSString *keyword = self.keywords[i];
        if (keyword == nil) continue;
        if (![keyword isKindOfClass:NSString.class]) keyword = [keyword description];
        
        CGFloat width = [keyword sizeWithAttributes:@{NSFontAttributeName:kNormalFont(12)}].width + marginRL;
    
        UIButton *button = [[UIButton alloc] init];
        button.backgroundColor = [UIColor whiteColor];
        button.titleLabel.lineBreakMode = NSLineBreakByTruncatingTail;
        button.titleLabel.font = kNormalFont(12);
//        button.layer.cornerRadius = 4;
//        button.layer.borderColor = kColor999999.CGColor;
//        button.layer.borderWidth = 1;
        [button setTitle:keyword forState:UIControlStateNormal];
        [button setTitleColor:kColor666666 forState:UIControlStateNormal];
        [button addTarget:self action:@selector(itemEvent:) forControlEvents:UIControlEventTouchUpInside];
        // 一行显示不下
        if (width > kDeviceWidth-20) {
            currentY += currentX == 10 ? 0:(lineH+spaceY); // 第一行已经有的话折行 否则就显示在第一行
            currentX = 10;
            button.frame = CGRectMake(currentX, currentY, kDeviceWidth-20, lineH);
            currentX = 10; //
            currentY += lineH+spaceY;
        }
         // 剩余的空间 能显示下
        else if (kDeviceWidth-currentX-25 > width) {
            button.frame = CGRectMake(currentX, currentY, width, lineH);
            currentX += width+spaceX;
        }
        // 剩余的空间 显示不下 需要折行显示(但是这一行还没显示满 故不更新currentY)
        else{
            currentY += lineH+spaceY;
            currentX = 10;
            button.frame = CGRectMake(currentX, currentY, width, lineH);
            currentX += width+spaceX;
        }
        
        [self addSubview:button];
    }
    self.frame = CGRectMake(0, 0, kDeviceWidth, currentY+lineH+10);
}

#pragma mark   -  数据
/**  获取当前关键字*/
- (NSMutableArray *)keywords{
    NSString *path = [SearchHistoryView getFilePath];
    _keywords = [NSMutableArray arrayWithContentsOfFile:path];
    
    if (_keywords == nil) {
        _keywords = [NSMutableArray array];
    }
    return _keywords;
}

/**  保存关键字*/
+ (BOOL)saveKeyword:(NSString *)keyword{
    
    if (keyword == nil || keyword.trim.length == 0) return NO;
    
    NSString *path = [self getFilePath];
    NSMutableArray *keywords = [NSMutableArray arrayWithContentsOfFile:path];
    
    // 空的
    if (keywords == nil) {
        keywords = [NSMutableArray array];
    }
    
    // 已经把包含
    if ([keywords containsObject:keyword]) {
        [keywords removeObject:keyword];
    }
    [keywords insertObject:keyword atIndex:0];
    
    // 超过十个
    if (keywords.count >10) {
        [keywords removeLastObject];
    }

    return [keywords writeToFile:path atomically:YES];
}

#pragma mark   -  事件
- (void)itemEvent:(UIButton *)button{
    
    if (_handle) {
        NSInteger index = [self.keywords indexOfObject:button.currentTitle];
        self.handle(button.currentTitle, index);
    }
    
    if ([SearchHistoryView saveKeyword:button.currentTitle]) {
        NSLog(@"保存搜索词成功");
    }
    
    [self removeFromSuperview];
}

/**  清除所有关键字*/
- (void)clearKeywords{
    NSString *path = [SearchHistoryView getFilePath];
    NSMutableArray *keywords = [NSMutableArray arrayWithContentsOfFile:path];
    [keywords removeAllObjects];
    [keywords writeToFile:path atomically:YES];
    [self reloadData];
    [self removeFromSuperview];
}


+ (NSString *)getFilePath{
    
    // 获取 document 路径
    NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    // 获取 document下 文件夹路径
    NSString *directory = [document stringByAppendingPathComponent:@"AntiFakeChain"];
    
    // 判断文件夹是否存在
    BOOL isDirectory;
    BOOL isExistDirectory = [[NSFileManager defaultManager] fileExistsAtPath:directory isDirectory:&isDirectory] && isDirectory;
    
    // 如果不存在创建文件夹
    if (isExistDirectory == NO){
        [[NSFileManager defaultManager] createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    // 获取文件路径
    NSString *path =  [directory stringByAppendingPathComponent:@"SeachHistory.plist"];
    
    return path;
}
@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值