iOS开发-实现热门话题标签tag显示控件

iOS开发-实现热门话题标签tag显示控件

话题标签tag显示非常常见,如选择你的兴趣,选择关注的群,超话,话题等等。

一、效果图

二、实现代码

由于显示的是在列表中,这里整体控件是放在UITableViewCell中的。

2.1 标签tag按钮实现

自定义标签tag按钮INRmdTopicButton

INRmdTopicButton.h

objectivec 复制代码
@interface INRmdTopicButton : UIControl

@property (nonatomic, strong) NSString *topicName;
@property (nonatomic, assign) CGFloat showTopicWidth;

+ (CGFloat)topicWidth:(NSString *)name;

@end

INRmdTopicButton.m

objectivec 复制代码
@interface INRmdTopicButton ()

@property (nonatomic, strong) UIImageView *backImageView;       //图片控件
@property (nonatomic, strong) UIImageView *tbkImageView;       //图片控件
@property (nonatomic, strong) UILabel *titleLabel;

@end

@implementation INRmdTopicButton

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addSubview:self.backImageView];
        [self.backImageView addSubview:self.tbkImageView];
        [self.backImageView addSubview:self.titleLabel];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.backImageView.frame = self.bounds;
    self.tbkImageView.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.backImageView.frame), CGRectGetHeight(self.backImageView.frame) - kSmallPadding);
    self.titleLabel.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.backImageView.frame), kTopicNameHeight);
}

- (void)setTopicName:(NSString *)topicName {
    _topicName = (topicName?topicName:@"");
    self.titleLabel.text = _topicName;
    [self setNeedsLayout];
}

+ (CGFloat)topicWidth:(NSString *)name {
    CGSize topicSize = [name sizeWithFont:[UIFont systemFontOfSize:12] forMaxSize:CGSizeMake(MAXFLOAT, kTopicHeight)];
    return topicSize.width + 2*kSmallPadding;
}

#pragma mark - SETTER/GETTER
- (UIImageView *)backImageView {
    if (!_backImageView) {
        _backImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _backImageView.userInteractionEnabled = YES;
        _backImageView.backgroundColor = [UIColor clearColor];
    }
    return _backImageView;
}

- (UIImageView *)tbkImageView {
    if (!_tbkImageView) {
        _tbkImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _tbkImageView.userInteractionEnabled = YES;
        _tbkImageView.backgroundColor = [UIColor clearColor];
        UIImage *image = [UIImage imageNamed:@"bk_topic_r"];
        image = [image stretchableImageWithLeftCapWidth:floorf(image.size.width * 0.5) topCapHeight:floorf(image.size.height * 0.5)];
        _tbkImageView.image = image;
    }
    return _tbkImageView;
}

- (UILabel *)titleLabel {
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _titleLabel.font = [UIFont systemFontOfSize:12];
        _titleLabel.textAlignment = NSTextAlignmentCenter;
        _titleLabel.textColor = [UIColor colorWithHexString:@"555555"];
        _titleLabel.backgroundColor = [UIColor clearColor];
    }
    return _titleLabel;
}

@end

2.2 显示排列标签tag

显示标题tag时候,需要排列按钮

objectivec 复制代码
INRmdTopicButton *lastButton = nil;
    for (UIView *subView in self.topicBKImageView.subviews) {
        if ([subView isKindOfClass:[INRmdTopicButton class]]) {
            INRmdTopicButton *button = (INRmdTopicButton *)subView;
            button.hidden = NO;
            if (lastButton) {
                if (CGRectGetMaxX(lastButton.frame) + button.showTopicWidth + kSmallPadding > maxWidth) {
                    button.frame = CGRectMake(0.0, CGRectGetMaxY(lastButton.frame), button.showTopicWidth, kTopicHeight);
                } else {
                    button.frame = CGRectMake(CGRectGetMaxX(lastButton.frame) + kSmallPadding, CGRectGetMinY(lastButton.frame), button.showTopicWidth, kTopicHeight);
                }
            } else {
                button.frame = CGRectMake(originX, originY, button.showTopicWidth, kTopicHeight);
            }
            
            if (CGRectGetMaxY(button.frame) > maxHeight) {
                button.hidden = YES;
            } else {
                button.hidden = NO;
            }
            
            lastButton = button;
        }
    }

这里还加了拖动手势UIPanGestureRecognizer,当往左拖动的时候会显示松开换一换的功能。调用接口实现。

objectivec 复制代码
#pragma mark - panGestureHandle
- (void)panGestureHandle:(UIPanGestureRecognizer *)pan{
    if (pan.state == UIGestureRecognizerStateBegan) {
        NSLog(@"UIGestureRecognizerStateBegan");
        self.startPoint = [pan translationInView:self];
    } if (pan.state == UIGestureRecognizerStateChanged) {
        NSLog(@"UIGestureRecognizerStateChanged");
        
        CGPoint point = [pan translationInView:self];
        CGFloat xDistance = point.x - self.startPoint.x;
        // 左右滑动
        NSLog(@"左右滑动");
        if (xDistance > 0) {
            NSLog(@"向右滑动");
            CGRect backFrame = self.topicBKImageView.frame;
            backFrame.origin.x = kMidPadding;
            self.topicBKImageView.frame = backFrame;
        } else {
            NSLog(@"向左滑动");
            CGRect backFrame = self.topicBKImageView.frame;
            backFrame.origin.x = kMidPadding + xDistance*0.5;
            self.topicBKImageView.frame = backFrame;
        }
        
    } else {
        // if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled || pan.state == UIGestureRecognizerStateFailed)
        NSLog(@"UIGestureRecognizerStateEnded");
        CGRect backFrame = self.topicBKImageView.frame;
        backFrame.origin.x = kMidPadding;
        [UIView animateWithDuration:0.55 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:7.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.topicBKImageView.frame = backFrame;
        } completion:^(BOOL finished) {
            
        }];
    }
}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

2.3 完整代码如下

INRecommentTopicCell.h

objectivec 复制代码
#import <UIKit/UIKit.h>

@interface INRmdTopicButton : UIControl

@property (nonatomic, strong) NSString *topicName;
@property (nonatomic, assign) CGFloat showTopicWidth;

+ (CGFloat)topicWidth:(NSString *)name;

@end

/**
 推荐的话题
 */
@interface INRecommentTopicCell : UITableViewCell

+ (CGFloat)cellHeight;

@end

INRecommentTopicCell.m

objectivec 复制代码
#import "INRecommentTopicCell.h"
#import "UIColor+Addition.h"
#import "NSString+Size.h"

static CGFloat kCellHeight = 260.0;

static CGFloat kCellHorBGPadding = 10.0f;
static CGFloat kCellVerBGPadding = 5.0f;

static CGFloat kTitleHeight = 44.0f;
static CGFloat kMidPadding = 10.0f;

static CGFloat kSmallPadding = 5.0f;
static CGFloat kTopicHeight = 40.0f;
static CGFloat kTopicNameHeight = 30.0f;

static CGFloat kExchangeBtnSize = 40.0f;
static CGFloat kTisWidth = 20.0f;

@interface INRmdTopicButton ()

@property (nonatomic, strong) UIImageView *backImageView;       //图片控件
@property (nonatomic, strong) UIImageView *tbkImageView;       //图片控件
@property (nonatomic, strong) UILabel *titleLabel;

@end

@implementation INRmdTopicButton

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addSubview:self.backImageView];
        [self.backImageView addSubview:self.tbkImageView];
        [self.backImageView addSubview:self.titleLabel];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.backImageView.frame = self.bounds;
    self.tbkImageView.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.backImageView.frame), CGRectGetHeight(self.backImageView.frame) - kSmallPadding);
    self.titleLabel.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.backImageView.frame), kTopicNameHeight);
}

- (void)setTopicName:(NSString *)topicName {
    _topicName = (topicName?topicName:@"");
    self.titleLabel.text = _topicName;
    [self setNeedsLayout];
}

+ (CGFloat)topicWidth:(NSString *)name {
    CGSize topicSize = [name sizeWithFont:[UIFont systemFontOfSize:12] forMaxSize:CGSizeMake(MAXFLOAT, kTopicHeight)];
    return topicSize.width + 2*kSmallPadding;
}

#pragma mark - SETTER/GETTER
- (UIImageView *)backImageView {
    if (!_backImageView) {
        _backImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _backImageView.userInteractionEnabled = YES;
        _backImageView.backgroundColor = [UIColor clearColor];
    }
    return _backImageView;
}

- (UIImageView *)tbkImageView {
    if (!_tbkImageView) {
        _tbkImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _tbkImageView.userInteractionEnabled = YES;
        _tbkImageView.backgroundColor = [UIColor clearColor];
        UIImage *image = [UIImage imageNamed:@"bk_topic_r"];
        image = [image stretchableImageWithLeftCapWidth:floorf(image.size.width * 0.5) topCapHeight:floorf(image.size.height * 0.5)];
        _tbkImageView.image = image;
    }
    return _tbkImageView;
}

- (UILabel *)titleLabel {
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _titleLabel.font = [UIFont systemFontOfSize:12];
        _titleLabel.textAlignment = NSTextAlignmentCenter;
        _titleLabel.textColor = [UIColor colorWithHexString:@"555555"];
        _titleLabel.backgroundColor = [UIColor clearColor];
    }
    return _titleLabel;
}

@end

/**
 推荐的话题
 */
@interface INRecommentTopicCell ()

@property (nonatomic, strong) UIImageView *backImageView;       //图片控件
@property (nonatomic, strong) UIImageView *contentBGImageView;       //图片控件
@property (nonatomic, strong) UIImageView *topicBKImageView;       //图片控件
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UIButton *exchangeButton;     // 更多

@property (nonatomic, strong) UILabel *tipsLabel;

@property (nonatomic) CGPoint startPoint;     // 开始点

@end

@implementation INRecommentTopicCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        // Initialization code
        
        self.backgroundColor = [UIColor clearColor];
        self.contentView.backgroundColor = [UIColor clearColor];
        [self.contentView addSubview:self.backImageView];
        [self.contentView addSubview:self.contentBGImageView];
        [self.contentBGImageView addSubview:self.titleLabel];
        [self.contentBGImageView addSubview:self.exchangeButton];
        [self.contentBGImageView addSubview:self.tipsLabel];
        [self.contentBGImageView addSubview:self.topicBKImageView];

        [self setupRmdTopicViews];
        
        UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureHandle:)];
        panGesture.minimumNumberOfTouches = 1;
        panGesture.maximumNumberOfTouches = 1;
        panGesture.delegate = self;
        [self.contentBGImageView addGestureRecognizer:panGesture];
    }
    return self;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    self.backImageView.frame = CGRectMake(kCellHorBGPadding, kCellVerBGPadding, CGRectGetWidth(self.bounds) - 2*kCellHorBGPadding, CGRectGetHeight(self.bounds) - 2*kCellVerBGPadding);
    
    self.contentBGImageView.frame = CGRectMake(kCellHorBGPadding, kCellVerBGPadding, CGRectGetWidth(self.bounds) - 2*kCellHorBGPadding, CGRectGetHeight(self.bounds) - 2*kCellVerBGPadding);

    self.titleLabel.frame = CGRectMake(kMidPadding, 0.0, CGRectGetWidth(self.backImageView.frame) - 3*kMidPadding - kExchangeBtnSize, kTitleHeight);
    
    self.exchangeButton.frame = CGRectMake(CGRectGetWidth(self.backImageView.frame) - kMidPadding - kExchangeBtnSize, (kTitleHeight - kExchangeBtnSize)/2, kExchangeBtnSize, kExchangeBtnSize);
    
    CGFloat height = CGRectGetHeight(self.backImageView.frame) - CGRectGetMaxY(self.titleLabel.frame);
    self.tipsLabel.frame = CGRectMake(CGRectGetWidth(self.backImageView.frame) - kMidPadding - kTisWidth, 0.0, kTisWidth, height);
    
    self.topicBKImageView.frame = CGRectMake(kMidPadding, CGRectGetMaxY(self.titleLabel.frame), CGRectGetWidth(self.backImageView.frame) - 2*kMidPadding, height);
    
    CGFloat maxWidth = CGRectGetWidth(self.topicBKImageView.frame);
    CGFloat maxHeight = CGRectGetHeight(self.topicBKImageView.frame);
    
    CGFloat originX = 0.0;
    CGFloat originY = 0.0;

    INRmdTopicButton *lastButton = nil;
    for (UIView *subView in self.topicBKImageView.subviews) {
        if ([subView isKindOfClass:[INRmdTopicButton class]]) {
            INRmdTopicButton *button = (INRmdTopicButton *)subView;
            button.hidden = NO;
            if (lastButton) {
                if (CGRectGetMaxX(lastButton.frame) + button.showTopicWidth + kSmallPadding > maxWidth) {
                    button.frame = CGRectMake(0.0, CGRectGetMaxY(lastButton.frame), button.showTopicWidth, kTopicHeight);
                } else {
                    button.frame = CGRectMake(CGRectGetMaxX(lastButton.frame) + kSmallPadding, CGRectGetMinY(lastButton.frame), button.showTopicWidth, kTopicHeight);
                }
            } else {
                button.frame = CGRectMake(originX, originY, button.showTopicWidth, kTopicHeight);
            }
            
            if (CGRectGetMaxY(button.frame) > maxHeight) {
                button.hidden = YES;
            } else {
                button.hidden = NO;
            }
            
            lastButton = button;
        }
    }
}

- (void)setupRmdTopicViews {
    for (UIView *subView in self.topicBKImageView.subviews) {
        if ([subView isKindOfClass:[INRmdTopicButton class]]) {
            [subView removeFromSuperview];
        }
    }
    
    for (NSInteger index = 0; index < 15; index ++) {
        INRmdTopicButton *button = [[INRmdTopicButton alloc] initWithFrame:CGRectZero];
        button.tag = index;
        [self.topicBKImageView addSubview:button];
        
        if (index % 5 == 0) {
            button.topicName = @"#读书交流";
        } else if (index % 5 == 1) {
            button.topicName = @"#爱手工生活";
        } else if (index % 5 == 2) {
            button.topicName = @"#精致的佛系生活";
        } else if (index % 5 == 3) {
            button.topicName = @"#数码发烧友";
        } else if (index % 5 == 4) {
            button.topicName = @"#晒晒你的心情";
        } else {
            button.topicName = @"#说说身边事";
        }
        button.showTopicWidth = [INRmdTopicButton topicWidth:button.topicName];
    }
    
    [self setNeedsLayout];
}


- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
    [super setSelected:selected animated:animated];

    // Configure the view for the selected state
}

+ (CGFloat)cellHeight {
    return kCellHeight;
}

#pragma mark - Actions
- (void)exchangeButtonAction {
    
}

#pragma mark - SETTER/GETTER
- (UIImageView *)backImageView {
    if (!_backImageView) {
        _backImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _backImageView.userInteractionEnabled = YES;
        _backImageView.backgroundColor = [UIColor whiteColor];
        _backImageView.layer.cornerRadius = 2.0;
        _backImageView.layer.shadowColor = [UIColor colorWithHexString:@"9bb9ef"].CGColor;
        _backImageView.layer.shadowOffset = CGSizeMake(0, 3);
        _backImageView.layer.shadowOpacity = 0.3;
        _backImageView.layer.shadowRadius = 3.0;
    }
    return _backImageView;
}

- (UIImageView *)contentBGImageView {
    if (!_contentBGImageView) {
        _contentBGImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _contentBGImageView.userInteractionEnabled = YES;
        _contentBGImageView.backgroundColor = [UIColor whiteColor];
        _contentBGImageView.layer.cornerRadius = 2.0;
        _contentBGImageView.layer.masksToBounds = YES;
        _contentBGImageView.clipsToBounds = YES;
    }
    return _contentBGImageView;
}

- (UIImageView *)topicBKImageView {
    if (!_topicBKImageView) {
        _topicBKImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _topicBKImageView.userInteractionEnabled = YES;
        _topicBKImageView.backgroundColor = [UIColor whiteColor];
        _topicBKImageView.clipsToBounds = YES;
    }
    return _topicBKImageView;
}

- (UILabel *)titleLabel {
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _titleLabel.font = [UIFont systemFontOfSize:18];
        _titleLabel.textColor = [UIColor colorWithHexString:@"131619"];
        _titleLabel.backgroundColor = [UIColor clearColor];
        _titleLabel.text = @"热门话题";
    }
    return _titleLabel;
}

- (UILabel *)tipsLabel {
    if (!_tipsLabel) {
        _tipsLabel = [[UILabel alloc] initWithFrame:CGRectZero];
        _tipsLabel.font = [UIFont systemFontOfSize:12];
        _tipsLabel.textColor = [UIColor colorWithHexString:@"9a9b9c"];
        _tipsLabel.backgroundColor = [UIColor clearColor];
        _tipsLabel.numberOfLines = 0;
        _tipsLabel.textAlignment = NSTextAlignmentCenter;
        _tipsLabel.text = @"松\n开\n换\n一\n换";
    }
    return _tipsLabel;
}

- (UIButton *)exchangeButton {
    if (!_exchangeButton) {
        _exchangeButton = [UIButton buttonWithType:UIButtonTypeCustom];
        [_exchangeButton setImage:[UIImage imageNamed:@"ic_topic_exchange"] forState:UIControlStateNormal];
        [_exchangeButton addTarget:self action:@selector(exchangeButtonAction) forControlEvents:UIControlEventTouchUpInside];
    }
    return _exchangeButton;
}

#pragma mark - panGestureHandle
- (void)panGestureHandle:(UIPanGestureRecognizer *)pan{
    if (pan.state == UIGestureRecognizerStateBegan) {
        NSLog(@"UIGestureRecognizerStateBegan");
        self.startPoint = [pan translationInView:self];
    } if (pan.state == UIGestureRecognizerStateChanged) {
        NSLog(@"UIGestureRecognizerStateChanged");
        
        CGPoint point = [pan translationInView:self];
        CGFloat xDistance = point.x - self.startPoint.x;
        // 左右滑动
        NSLog(@"左右滑动");
        if (xDistance > 0) {
            NSLog(@"向右滑动");
            CGRect backFrame = self.topicBKImageView.frame;
            backFrame.origin.x = kMidPadding;
            self.topicBKImageView.frame = backFrame;
        } else {
            NSLog(@"向左滑动");
            CGRect backFrame = self.topicBKImageView.frame;
            backFrame.origin.x = kMidPadding + xDistance*0.5;
            self.topicBKImageView.frame = backFrame;
        }
        
    } else {
        // if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateCancelled || pan.state == UIGestureRecognizerStateFailed)
        NSLog(@"UIGestureRecognizerStateEnded");
        CGRect backFrame = self.topicBKImageView.frame;
        backFrame.origin.x = kMidPadding;
        [UIView animateWithDuration:0.55 delay:0.0 usingSpringWithDamping:0.5 initialSpringVelocity:7.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
            self.topicBKImageView.frame = backFrame;
        } completion:^(BOOL finished) {
            
        }];
    }
}

-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
    return YES;
}

@end

三、小结

iOS开发-实现热门话题标签tag显示控件

话题标签tag显示非常常见,如选择你的兴趣,选择关注的群,超话,话题等等。

学习记录,每天不停进步。

相关推荐
学习非暴力沟通的程序员2 小时前
Mac 自动定时打开指定URL(无日历版)操作文档
macos
Digitally3 小时前
如何通过蓝牙将联系人从 iPhone 传输到 Android
android·ios·iphone
90后的晨仔3 小时前
2025年11月27日年解决隐私清单导致审核总是提示二进制无效的问题
ios
songgeb5 小时前
iOS Audio后台模式下能否执行非Audio逻辑
ios·swift
如此风景5 小时前
Swift的Extension简单说明
ios
kk哥889912 小时前
iOS开发:关于日志框架
网络·ios·cocoa
mixboot21 小时前
macOS Homebrew 安装 Nmap
macos·nmap
Haha_bj21 小时前
Swift UI 状态管理
ios·app
2501_916007471 天前
iOS 应用性能测试的工程化流程,构建从指标采集到问题归因的多工具协同测试体系
android·ios·小程序·https·uni-app·iphone·webview
源码_V_saaskw1 天前
JAVA国际版同城跑腿源码快递代取帮买帮送同城服务源码支持Android+IOS+H5
android·java·ios·微信小程序