iOS 笔记

仿今日头条的滚动标题栏

2019-03-21  本文已影响14人  道道明明白白

前提:代码即插即用,不依赖任何第三方和其他类,使用方便。

效果展示:

今日头条(极速版)效果如下:
![BF79101F3806AF5E9EE3FDAD8A702E31.gif](https://img.haomeiwen.com/i2325948/4fdd40bd181b932a.gif?imageMogr2/auto-orient/strip)
ZSTitleSelectedView效果如下:
33F1E42049654AB96D2206F5D0A63677-Segment 1.gif
封装的代码如下:

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

/**
 zs20190320 滚动的title 
 */
@interface ZSTitleSelectedView : UIView

@property (nonatomic, strong) NSMutableArray *arrayTitles;       /**< zs20190320 标题数组  */



/**
 zs20190321 刷新标题数据源

 @param arrayTitles 数据源数组
 */
- (void)updateArrayTitles:(NSMutableArray *)arrayTitles;

@end

NS_ASSUME_NONNULL_END

#import "ZSTitleSelectedView.h"

#define kTagBtnsBase  1903200929  //zs20190321 多个标题按钮 tag初值
#define kRGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
@interface ZSTitleSelectedView()

@property (nonatomic, strong) UIScrollView *scrollView;      /**< zs20190320 滚动视图  */

@property (nonatomic, strong) UIButton *btnLastSelected;       /**< zs20190320 上次选中的按钮 */

@end

@implementation ZSTitleSelectedView

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self addContentView];
    }
    return self;
}
- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self addContentView];
    }
    return self;
}
- (void)layoutSubviews
{
    [super layoutSubviews];
    self.scrollView.frame = self.bounds;
}

- (void)updateArrayTitles:(NSMutableArray *)arrayTitles
{
    _arrayTitles = arrayTitles;
    [self reloadBtnsTitles];
}

#pragma mark - private
- (void)addContentView
{
    self.scrollView.backgroundColor = kRGB(125, 185, 240);
    [self addSubview:self.scrollView];
}
- (void)onClickAllBtns:(UIButton*)btn
{
    if (btn.selected) {
        return;
    }
    _btnLastSelected.selected = NO;
    btn.selected = YES;
    _btnLastSelected = btn;
    
    if (self.scrollView.contentSize.width < self.frame.size.width) {
        return;
    }
    //zs20190320 进行位置偏移 将选中的标题 移动到中间位置
    if (btn.center.x > self.frame.size.width/2.0) {
        if (btn.center.x - self.frame.size.width/2.0 < (self.scrollView.contentSize.width - self.frame.size.width)) {
            [self.scrollView setContentOffset:CGPointMake(btn.center.x - self.frame.size.width/2.0, 0) animated:YES];
        } else {
            [self.scrollView setContentOffset:CGPointMake((self.scrollView.contentSize.width - self.frame.size.width), 0) animated:YES];
        }
    } else {
            [self.scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
    }
}
- (void)reloadBtnsTitles
{
    for (int i = 0; i < self.arrayTitles.count ; i ++) {
        
        UIButton *btnTitle = [UIButton buttonWithType:UIButtonTypeCustom];
        [btnTitle setTitle:_arrayTitles[i] forState:(UIControlStateNormal)];
        btnTitle.titleLabel.font = [UIFont systemFontOfSize:14];
        [btnTitle setTitleColor:kRGB(31, 31, 31) forState:(UIControlStateNormal)];
        [btnTitle setTitleColor:kRGB(246, 78, 79) forState:(UIControlStateSelected)];
        btnTitle.tag = i + kTagBtnsBase;
        if (i == 0) {
            _btnLastSelected = btnTitle;
            btnTitle.selected = YES;
            btnTitle.frame = CGRectMake(15,
                                        0,
                                        [self getTextWidth:self.arrayTitles[i] font:14] + 10,
                                        self.frame.size.height);
        } else {
            UIButton *btnLast = (UIButton*)[self.scrollView viewWithTag:i + kTagBtnsBase -1];
            btnTitle.frame = CGRectMake(btnLast.frame.origin.x + btnLast.frame.size.width + 10,
                                        0,
                                        [self getTextWidth:self.arrayTitles[i] font:14] + 10,
                                        self.frame.size.height);
        }
        [btnTitle addTarget:self action:@selector(onClickAllBtns:) forControlEvents:(UIControlEventTouchUpInside)];
        [_scrollView addSubview:btnTitle];
    }
    
    
    if (self.arrayTitles.count > 1) {//zs20190321 保证两个及两个以上的标题
        
        UIButton *btnLast = [self.scrollView viewWithTag:self.arrayTitles.count - 1 + kTagBtnsBase];
        //zs20190321 判断最后一个按钮的位置 是否超过父视图 如果没超过则将剩余的宽度补到两个按钮之间的间隙上
        if (btnLast.frame.origin.x + btnLast.frame.size.width + 15 < self.frame.size.width) {
            
            //zs20190321 如果标题在屏幕上能全部展示 则做位置做均匀分配处理
            CGFloat widthPara = self.frame.size.width - (btnLast.frame.origin.x + btnLast.frame.size.width + 15);
            CGFloat widthAdd = widthPara/(self.arrayTitles.count -1);
            for (int i = 1; i < self.arrayTitles.count; i ++) {
                UIButton *btn= (UIButton*)[self.scrollView viewWithTag:i + kTagBtnsBase];
                btn.frame = CGRectMake(btn.frame.origin.x + widthAdd,
                                       btn.frame.origin.y,
                                       btn.frame.size.width,
                                       btn.frame.size.height);
                if (i > 1) {
                    UIButton *btnFront = (UIButton*)[self.scrollView viewWithTag:i + kTagBtnsBase -1];
                    btn.frame = CGRectMake(btnFront.frame.origin.x + btnFront.frame.size.width + 10 + widthAdd,
                                           btn.frame.origin.y,
                                           btn.frame.size.width,
                                           btn.frame.size.height);
                }
            }
        } else {//zs20190321 所有标题在屏幕上展示不下 需要滚动
            _scrollView.contentSize = CGSizeMake(btnLast.frame.origin.x + btnLast.frame.size.width  + 15, self.frame.size.height);
        }
    }
    
    //zs20190321 如果只有一个标题或者两个标题 按照具体需求去适配吧
}

#pragma mark ------- 计算文本在对应字体下的长度
- (CGFloat)getTextWidth:(NSString*)text font:(CGFloat)fontPara
{
    if ([text isKindOfClass:[NSString class]]) {
        
        CGSize size = [text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:fontPara]}];
        return size.width;
    } else {
        return 0;
    }
}
#pragma mark - getter
- (UIScrollView *)scrollView
{
    if (_scrollView == nil) {
        _scrollView = [[UIScrollView alloc] init];
        _scrollView.showsHorizontalScrollIndicator = NO;
    }
    return _scrollView;
}

@end

客户端调用代码如下:
#import "ViewController.h"
#import "ZSTitleSelectedView.h"

@interface ViewController ()

@property (nonatomic, strong) ZSTitleSelectedView *viewTitleSelected;        /**< zs20190321 标题视图  */

@end

@implementation ViewController

- (void)viewDidLoad {
   
    [super viewDidLoad];

    [self.view addSubview:self.viewTitleSelected];
    
    self.viewTitleSelected.frame = CGRectMake(0, 31, self.view.frame.size.width, 40);

    NSMutableArray *arrayTitles = [NSMutableArray arrayWithObjects:
                                   @"推荐",
                                   @"视频",
                                   @"热点",
                                   @"北京",
                                   @"娱乐",
                                   @"音乐",
                                   @"图片",
                                   @"懂车帝",
                                   @"体育",
                                   @"财经",
                                   @"房产",
                                   @"国际",
                                   @"健康",
                                   @"科技",
                                   @"军事",
                                   @"历史",
                                   @"值点",
                                   @"小说",
                                   nil];
    [self.viewTitleSelected updateArrayTitles:arrayTitles];
}





- (ZSTitleSelectedView *)viewTitleSelected
{
    if (_viewTitleSelected == nil) {
        
        _viewTitleSelected = [[ZSTitleSelectedView alloc] init];
    }
    return _viewTitleSelected;
}
GitHub下载地址:https://github.com/zhiyoukaifa/ZSTitleSelectedView.git
上一篇下一篇

猜你喜欢

热点阅读