前提:代碼即插即用,不依賴任何第三方和其他類,使用方便。
效果展示:
今日頭條(極速版)效果如下:
![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 標題數(shù)組 */
/**
zs20190321 刷新標題數(shù)據(jù)源
@param arrayTitles 數(shù)據(jù)源數(shù)組
*/
- (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
客戶端調(diào)用代碼如下:
#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:
@"推薦",
@"視頻",
@"熱點",
@"北京",
@"娛樂",
@"音樂",
@"圖片",
@"懂車帝",
@"體育",
@"財經(jīng)",
@"房產(chǎn)",
@"國際",
@"健康",
@"科技",
@"軍事",
@"歷史",
@"值點",
@"小說",
nil];
[self.viewTitleSelected updateArrayTitles:arrayTitles];
}
- (ZSTitleSelectedView *)viewTitleSelected
{
if (_viewTitleSelected == nil) {
_viewTitleSelected = [[ZSTitleSelectedView alloc] init];
}
return _viewTitleSelected;
}