前提:代码即插即用,不依赖任何第三方和其他类,使用方便。
效果展示:
今日头条(极速版)效果如下:
![BF79101F3806AF5E9EE3FDAD8A702E31.gif](https://upload-images.jianshu.io/upload_images/2325948-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;
}