123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875 |
- //
- // 如遇到问题或有更好方案,请通过以下方式进行联系
- // QQ群:429899752
- // Email:kingsic@126.com
- // GitHub:https://github.com/kingsic/SGPagingView
- //
- // SGPageTitleView.m
- // SGPagingViewExample
- //
- // Created by kingsic on 17/4/10.
- // Copyright © 2017年 kingsic. All rights reserved.
- //
- #import "SGPageTitleView.h"
- #import "UIView+SGPagingView.h"
- #import "SGPageTitleViewConfigure.h"
- #define SGPageTitleViewWidth self.frame.size.width
- #define SGPageTitleViewHeight self.frame.size.height
- #pragma mark - - - SGPageTitleButton
- @interface SGPageTitleButton : UIButton
- @end
- @implementation SGPageTitleButton
- - (void)setHighlighted:(BOOL)highlighted {
-
- }
- @end
- #pragma mark - - - SGPageTitleView
- @interface SGPageTitleView ()
- /// SGPageTitleViewDelegate
- @property (nonatomic, weak) id<SGPageTitleViewDelegate> delegatePageTitleView;
- /// SGPageTitleView 配置信息
- @property (nonatomic, readwrite, strong) SGPageTitleViewConfigure *configure;
- /// scrollView
- @property (nonatomic, strong) UIScrollView *scrollView;
- /// 指示器
- @property (nonatomic, strong) UIView *indicatorView;
- /// 底部分割线
- @property (nonatomic, strong) UIView *bottomSeparator;
- /// 保存外界传递过来的标题数组
- @property (nonatomic, strong) NSArray *titleArr;
- /// 存储标题按钮的数组
- @property (nonatomic, strong) NSMutableArray *btnMArr;
- /// tempBtn
- @property (nonatomic, strong) UIButton *tempBtn;
- /// 记录所有按钮文字宽度
- @property (nonatomic, assign) CGFloat allBtnTextWidth;
- /// 记录所有子控件的宽度
- @property (nonatomic, assign) CGFloat allBtnWidth;
- /// 标记按钮下标
- @property (nonatomic, assign) NSInteger signBtnIndex;
- /// 开始颜色, 取值范围 0~1
- @property (nonatomic, assign) CGFloat startR;
- @property (nonatomic, assign) CGFloat startG;
- @property (nonatomic, assign) CGFloat startB;
- /// 完成颜色, 取值范围 0~1
- @property (nonatomic, assign) CGFloat endR;
- @property (nonatomic, assign) CGFloat endG;
- @property (nonatomic, assign) CGFloat endB;
- @end
- @implementation SGPageTitleView
- - (instancetype)initWithFrame:(CGRect)frame delegate:(id<SGPageTitleViewDelegate>)delegate titleNames:(NSArray *)titleNames configure:(SGPageTitleViewConfigure *)configure {
- if (self = [super initWithFrame:frame]) {
- self.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.77];
- if (delegate == nil) {
- @throw [NSException exceptionWithName:@"SGPagingView" reason:@"SGPageTitleView 的代理方法必须设置" userInfo:nil];
- }
- self.delegatePageTitleView = delegate;
- if (titleNames == nil) {
- @throw [NSException exceptionWithName:@"SGPagingView" reason:@"SGPageTitleView 的标题数组必须设置" userInfo:nil];
- }
- self.titleArr = titleNames;
- if (configure == nil) {
- @throw [NSException exceptionWithName:@"SGPagingView" reason:@"SGPageTitleView 的配置属性必须设置" userInfo:nil];
- }
- self.configure = configure;
-
- [self initialization];
- [self setupSubviews];
- }
- return self;
- }
- + (instancetype)pageTitleViewWithFrame:(CGRect)frame delegate:(id<SGPageTitleViewDelegate>)delegate titleNames:(NSArray *)titleNames configure:(SGPageTitleViewConfigure *)configure {
- return [[self alloc] initWithFrame:frame delegate:delegate titleNames:titleNames configure:configure];
- }
- - (void)initialization {
- _isTitleGradientEffect = YES;
- _isOpenTitleTextZoom = NO;
- _isShowIndicator = YES;
- _isNeedBounces = YES;
- _isShowBottomSeparator = YES;
- _selectedIndex = 0;
- _titleTextScaling = 0.1;
- }
- - (void)setupSubviews {
- // 0、处理偏移量
- UIView *tempView = [[UIView alloc] initWithFrame:CGRectZero];
- [self addSubview:tempView];
- // 1、添加 UIScrollView
- [self addSubview:self.scrollView];
- // 2、添加标题按钮
- [self setupTitleButtons];
- // 3、添加底部分割线
- [self addSubview:self.bottomSeparator];
- // 4、添加指示器
- [self.scrollView insertSubview:self.indicatorView atIndex:0];
- }
- #pragma mark - - - layoutSubviews
- - (void)layoutSubviews {
- [super layoutSubviews];
- // 选中按钮下标初始值
- UIButton *lastBtn = self.btnMArr.lastObject;
- if (lastBtn.tag >= _selectedIndex && _selectedIndex >= 0) {
- [self P_btn_action:self.btnMArr[_selectedIndex]];
- } else {
- return;
- }
- }
- #pragma mark - - - 懒加载
- - (NSArray *)titleArr {
- if (!_titleArr) {
- _titleArr = [NSArray array];
- }
- return _titleArr;
- }
- - (NSMutableArray *)btnMArr {
- if (!_btnMArr) {
- _btnMArr = [NSMutableArray array];
- }
- return _btnMArr;
- }
- - (UIScrollView *)scrollView {
- if (!_scrollView) {
- _scrollView = [[UIScrollView alloc] init];
- _scrollView.showsVerticalScrollIndicator = NO;
- _scrollView.showsHorizontalScrollIndicator = NO;
- _scrollView.alwaysBounceHorizontal = YES;
- _scrollView.frame = CGRectMake(0, 0, SGPageTitleViewWidth, SGPageTitleViewHeight);
- }
- return _scrollView;
- }
- - (UIView *)indicatorView {
- if (!_indicatorView) {
- _indicatorView = [[UIView alloc] init];
- if (self.configure.indicatorStyle == SGIndicatorStyleCover) {
- CGFloat tempIndicatorViewH = [self SG_heightWithString:[self.btnMArr[0] currentTitle] font:self.configure.titleFont];
- if (self.configure.indicatorHeight > self.SG_height) {
- _indicatorView.SG_y = 0;
- _indicatorView.SG_height = self.SG_height;
- } else if (self.configure.indicatorHeight < tempIndicatorViewH) {
- _indicatorView.SG_y = 0.5 * (self.SG_height - tempIndicatorViewH);
- _indicatorView.SG_height = tempIndicatorViewH;
- } else {
- _indicatorView.SG_y = 0.5 * (self.SG_height - self.configure.indicatorHeight);
- _indicatorView.SG_height = self.configure.indicatorHeight;
- }
-
- // 圆角处理
- if (self.configure.indicatorCornerRadius > 0.5 * _indicatorView.SG_height) {
- _indicatorView.layer.cornerRadius = 0.5 * _indicatorView.SG_height;
- } else {
- _indicatorView.layer.cornerRadius = self.configure.indicatorCornerRadius;
- }
-
- // 边框宽度及边框颜色
- _indicatorView.layer.borderWidth = self.configure.indicatorBorderWidth;
- _indicatorView.layer.borderColor = self.configure.indicatorBorderColor.CGColor;
-
- } else {
- CGFloat indicatorViewH = self.configure.indicatorHeight;
- _indicatorView.SG_height = indicatorViewH;
- _indicatorView.SG_y = self.SG_height - indicatorViewH;
- }
- _indicatorView.backgroundColor = self.configure.indicatorColor;
- }
- return _indicatorView;
- }
- - (UIView *)bottomSeparator {
- if (!_bottomSeparator) {
- _bottomSeparator = [[UIView alloc] init];
- CGFloat bottomSeparatorW = self.SG_width;
- CGFloat bottomSeparatorH = 0.5;
- CGFloat bottomSeparatorX = 0;
- CGFloat bottomSeparatorY = self.SG_height - bottomSeparatorH;
- _bottomSeparator.frame = CGRectMake(bottomSeparatorX, bottomSeparatorY, bottomSeparatorW, bottomSeparatorH);
- _bottomSeparator.backgroundColor = [UIColor lightGrayColor];
- }
- return _bottomSeparator;
- }
- #pragma mark - - - 计算字符串宽度
- - (CGFloat)SG_widthWithString:(NSString *)string font:(UIFont *)font {
- NSDictionary *attrs = @{NSFontAttributeName : font};
- return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.width;
- }
- #pragma mark - - - 计算字符串高度
- - (CGFloat)SG_heightWithString:(NSString *)string font:(UIFont *)font {
- NSDictionary *attrs = @{NSFontAttributeName : font};
- return [string boundingRectWithSize:CGSizeMake(0, 0) options:NSStringDrawingUsesLineFragmentOrigin attributes:attrs context:nil].size.height;
- }
- #pragma mark - - - 添加标题按钮
- - (void)setupTitleButtons {
- // 计算所有按钮的文字宽度
- [self.titleArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- CGFloat tempWidth = [self SG_widthWithString:obj font:self.configure.titleFont];
- self.allBtnTextWidth += tempWidth;
- }];
- // 所有按钮文字宽度 + 按钮之间的间隔
- self.allBtnWidth = self.configure.spacingBetweenButtons * (self.titleArr.count + 1) + self.allBtnTextWidth;
- self.allBtnWidth = ceilf(self.allBtnWidth);
-
- NSInteger titleCount = self.titleArr.count;
- if (self.allBtnWidth <= self.bounds.size.width) { // SGPageTitleView 静止样式
- CGFloat btnY = 0;
- CGFloat btnW = SGPageTitleViewWidth / self.titleArr.count;
- CGFloat btnH = 0;
- if (self.configure.indicatorStyle == SGIndicatorStyleDefault) {
- btnH = SGPageTitleViewHeight - self.configure.indicatorHeight;
- } else {
- btnH = SGPageTitleViewHeight;
- }
- for (NSInteger index = 0; index < titleCount; index++) {
- SGPageTitleButton *btn = [[SGPageTitleButton alloc] init];
- CGFloat btnX = btnW * index;
- btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
- btn.tag = index;
- btn.titleLabel.font = self.configure.titleFont;
- [btn setTitle:self.titleArr[index] forState:(UIControlStateNormal)];
- [btn setTitleColor:self.configure.titleColor forState:(UIControlStateNormal)];
- [btn setTitleColor:self.configure.titleSelectedColor forState:(UIControlStateSelected)];
- [btn addTarget:self action:@selector(P_btn_action:) forControlEvents:(UIControlEventTouchUpInside)];
- [self.btnMArr addObject:btn];
- [self.scrollView addSubview:btn];
-
- [self setupStartColor:self.configure.titleColor];
- [self setupEndColor:self.configure.titleSelectedColor];
- }
- self.scrollView.contentSize = CGSizeMake(SGPageTitleViewWidth, SGPageTitleViewHeight);
-
- } else { // SGPageTitleView 滚动样式
- CGFloat btnX = 0;
- CGFloat btnY = 0;
- CGFloat btnH = 0;
- if (self.configure.indicatorStyle == SGIndicatorStyleDefault) {
- btnH = SGPageTitleViewHeight - self.configure.indicatorHeight;
- } else {
- btnH = SGPageTitleViewHeight;
- }
- for (NSInteger index = 0; index < titleCount; index++) {
- SGPageTitleButton *btn = [[SGPageTitleButton alloc] init];
- CGFloat btnW = [self SG_widthWithString:self.titleArr[index] font:self.configure.titleFont] + self.configure.spacingBetweenButtons;
- btn.frame = CGRectMake(btnX, btnY, btnW, btnH);
- btnX = btnX + btnW;
- btn.tag = index;
- btn.titleLabel.font = self.configure.titleFont;
- [btn setTitle:self.titleArr[index] forState:(UIControlStateNormal)];
- [btn setTitleColor:self.configure.titleColor forState:(UIControlStateNormal)];
- [btn setTitleColor:self.configure.titleSelectedColor forState:(UIControlStateSelected)];
- [btn addTarget:self action:@selector(P_btn_action:) forControlEvents:(UIControlEventTouchUpInside)];
- [self.btnMArr addObject:btn];
- [self.scrollView addSubview:btn];
-
- [self setupStartColor:self.configure.titleColor];
- [self setupEndColor:self.configure.titleSelectedColor];
- }
-
- CGFloat scrollViewWidth = CGRectGetMaxX(self.scrollView.subviews.lastObject.frame);
- self.scrollView.contentSize = CGSizeMake(scrollViewWidth, SGPageTitleViewHeight);
- }
- }
- #pragma mark - - - 标题按钮的点击事件
- - (void)P_btn_action:(UIButton *)button {
- // 1、改变按钮的选择状态
- [self P_changeSelectedButton:button];
- // 2、滚动标题选中按钮居中
- if (self.allBtnWidth > SGPageTitleViewWidth) {
- [self P_selectedBtnCenter:button];
- }
- // 3、改变指示器的位置以及指示器宽度样式
- [self P_changeIndicatorViewLocationWithButton:button];
- // 4、pageTitleViewDelegate
- if ([self.delegatePageTitleView respondsToSelector:@selector(pageTitleView:selectedIndex:)]) {
- [self.delegatePageTitleView pageTitleView:self selectedIndex:button.tag];
- }
- // 5、标记按钮下标
- self.signBtnIndex = button.tag;
- }
- - (void)c_btn_action:(UIButton *)button {
- // 1、改变按钮的选择状态
- [self P_changeSelectedButton:button];
- // 2、滚动标题选中按钮居中
- if (self.allBtnWidth > SGPageTitleViewWidth) {
- [self P_selectedBtnCenter:button];
- }
- // 3、改变指示器的位置以及指示器宽度样式
- [self P_changeIndicatorViewLocationWithButton:button];
- // 4、pageTitleViewDelegate
-
- // 5、标记按钮下标
- self.signBtnIndex = button.tag;
- }
- #pragma mark - - - 改变按钮的选择状态
- - (void)P_changeSelectedButton:(UIButton *)button {
- if (self.tempBtn == nil) {
- button.selected = YES;
- self.tempBtn = button;
- } else if (self.tempBtn != nil && self.tempBtn == button){
- button.selected = YES;
- } else if (self.tempBtn != button && self.tempBtn != nil){
- self.tempBtn.selected = NO;
- button.selected = YES;
- self.tempBtn = button;
- }
- // 标题文字缩放属性
- if (self.isOpenTitleTextZoom) {
- [self.btnMArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
- UIButton *btn = obj;
- btn.transform = CGAffineTransformMakeScale(1, 1);
- }];
- button.transform = CGAffineTransformMakeScale(1 + self.titleTextScaling, 1 + self.titleTextScaling);
- }
- }
- #pragma mark - - - 滚动标题选中按钮居中
- - (void)P_selectedBtnCenter:(UIButton *)centerBtn {
- // 计算偏移量
- CGFloat offsetX = centerBtn.center.x - SGPageTitleViewWidth * 0.5;
- if (offsetX < 0) offsetX = 0;
- // 获取最大滚动范围
- CGFloat maxOffsetX = self.scrollView.contentSize.width - SGPageTitleViewWidth;
- if (offsetX > maxOffsetX) offsetX = maxOffsetX;
- // 滚动标题滚动条
- [self.scrollView setContentOffset:CGPointMake(offsetX, 0) animated:YES];
- }
- #pragma mark - - - 改变指示器的位置以及指示器宽度样式
- - (void)P_changeIndicatorViewLocationWithButton:(UIButton *)button {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- self.indicatorView.SG_width = self.configure.indicatorFixedWidth;
- self.indicatorView.SG_centerX = button.SG_centerX;
-
- } else if (self.configure.indicatorStyle == SGIndicatorStyleDynamic) {
- self.indicatorView.SG_width = self.configure.indicatorDynamicWidth;
- self.indicatorView.SG_centerX = button.SG_centerX;
-
- } else {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:button.currentTitle font:self.configure.titleFont];
- if (tempIndicatorWidth > button.SG_width) {
- tempIndicatorWidth = button.SG_width;
- }
- self.indicatorView.SG_width = tempIndicatorWidth;
- self.indicatorView.SG_centerX = button.SG_centerX;
- }
- }];
- }
- #pragma mark - - - 给外界提供的方法
- - (void)setPageTitleViewWithProgress:(CGFloat)progress originalIndex:(NSInteger)originalIndex targetIndex:(NSInteger)targetIndex {
- // 1、取出 originalBtn/targetBtn
- UIButton *originalBtn = self.btnMArr[originalIndex];
- UIButton *targetBtn = self.btnMArr[targetIndex];
- self.signBtnIndex = targetBtn.tag;
- // 2、 滚动标题选中居中
- [self P_selectedBtnCenter:targetBtn];
- // 3、处理指示器的逻辑
- if (self.allBtnWidth <= self.bounds.size.width) { /// SGPageTitleView 不可滚动
- if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleDefault) {
- [self P_smallIndicatorScrollStyleDefaultWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
- } else {
- [self P_smallIndicatorScrollStyleHalfEndWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
- }
- } else { /// SGPageTitleView 可滚动
- if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleDefault) {
- [self P_indicatorScrollStyleDefaultWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
- } else {
- [self P_indicatorScrollStyleHalfEndWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
- }
- }
- // 4、颜色的渐变(复杂)
- if (self.isTitleGradientEffect) {
- [self P_isTitleGradientEffectWithProgress:progress originalBtn:originalBtn targetBtn:targetBtn];
- }
- // 5 、标题文字缩放属性
- if (self.isOpenTitleTextZoom) {
- // 左边缩放
- originalBtn.transform = CGAffineTransformMakeScale((1 - progress) * self.titleTextScaling + 1, (1 - progress) * self.titleTextScaling + 1);
- // 右边缩放
- targetBtn.transform = CGAffineTransformMakeScale(progress * self.titleTextScaling + 1, progress * self.titleTextScaling + 1);
- }
- }
- /**
- * 根据下标重置标题文字
- *
- * @param index 标题所对应的下标
- * @param title 新标题名
- */
- - (void)resetTitleWithIndex:(NSInteger)index newTitle:(NSString *)title {
- if (index < self.btnMArr.count) {
- UIButton *button = (UIButton *)self.btnMArr[index];
- [button setTitle:title forState:UIControlStateNormal];
- if (self.signBtnIndex == index) {
- if (self.configure.indicatorStyle == SGIndicatorStyleDefault || self.configure.indicatorStyle == SGIndicatorStyleCover) {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:button.currentTitle font:self.configure.titleFont];
- if (tempIndicatorWidth > button.SG_width) {
- tempIndicatorWidth = button.SG_width;
- }
- self.indicatorView.SG_width = tempIndicatorWidth;
- self.indicatorView.SG_centerX = button.SG_centerX;
- }
- }
- }
- }
- #pragma mark - - - SGPageTitleView 静止样式下指示器默认滚动样式(SGIndicatorScrollStyleDefault)
- - (void)P_smallIndicatorScrollStyleDefaultWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
- // 1、改变按钮的选择状态
- if (progress >= 0.8) { /// 此处取 >= 0.8 而不是 1.0 为的是防止用户滚动过快而按钮的选中状态并没有改变
- [self P_changeSelectedButton:targetBtn];
- }
-
- if (self.configure.indicatorStyle == SGIndicatorStyleDynamic) {
- NSInteger originalBtnTag = originalBtn.tag;
- NSInteger targetBtnTag = targetBtn.tag;
- // 按钮之间的距离
- CGFloat distance = self.SG_width / self.titleArr.count;
- if (originalBtnTag <= targetBtnTag) { // 往左滑
- if (progress <= 0.5) {
- self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * progress * distance;
- } else {
- CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (distance - self.configure.indicatorDynamicWidth) - self.configure.indicatorDynamicWidth;
- self.indicatorView.SG_x = targetBtnIndicatorX + 2 * (progress - 1) * distance;
- self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * (1 - progress) * distance;
- }
- } else {
- if (progress <= 0.5) {
- CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - 0.5 * (distance - self.configure.indicatorDynamicWidth) - self.configure.indicatorDynamicWidth;
- self.indicatorView.SG_x = originalBtnIndicatorX - 2 * progress * distance;
- self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * progress * distance;
- } else {
- CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (distance - self.configure.indicatorDynamicWidth);
- self.indicatorView.SG_x = targetBtnIndicatorX; // 这句代码必须写,防止滚动结束之后指示器位置存在偏差,这里的偏差是由于 progress >= 0.8 导致的
- self.indicatorView.SG_width = self.configure.indicatorDynamicWidth + 2 * (1 - progress) * distance;
- }
- }
-
- } else if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (self.SG_width / self.titleArr.count - self.configure.indicatorFixedWidth) - self.configure.indicatorFixedWidth;
- CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - 0.5 * (self.SG_width / self.titleArr.count - self.configure.indicatorFixedWidth) - self.configure.indicatorFixedWidth;
- CGFloat totalOffsetX = targetBtnIndicatorX - originalBtnIndicatorX;
- self.indicatorView.SG_x = originalBtnIndicatorX + progress * totalOffsetX;
-
- } else {
- /// 1、计算 indicator 偏移量
- // targetBtn 文字宽度
- CGFloat targetBtnTextWidth = [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
- CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - targetBtnTextWidth - 0.5 * (self.SG_width / self.titleArr.count - targetBtnTextWidth + self.configure.indicatorAdditionalWidth);
- // originalBtn 文字宽度
- CGFloat originalBtnTextWidth = [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
- CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - originalBtnTextWidth - 0.5 * (self.SG_width / self.titleArr.count - originalBtnTextWidth + self.configure.indicatorAdditionalWidth);
- CGFloat totalOffsetX = targetBtnIndicatorX - originalBtnIndicatorX;
-
- /// 2、计算文字之间差值
- // 按钮宽度的距离
- CGFloat btnWidth = self.SG_width / self.titleArr.count;
- // targetBtn 文字右边的 x 值
- CGFloat targetBtnRightTextX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (btnWidth - targetBtnTextWidth);
- // originalBtn 文字右边的 x 值
- CGFloat originalBtnRightTextX = CGRectGetMaxX(originalBtn.frame) - 0.5 * (btnWidth - originalBtnTextWidth);
- CGFloat totalRightTextDistance = targetBtnRightTextX - originalBtnRightTextX;
-
- // 计算 indicatorView 滚动时 x 的偏移量
- CGFloat offsetX = totalOffsetX * progress;
- // 计算 indicatorView 滚动时文字宽度的偏移量
- CGFloat distance = progress * (totalRightTextDistance - totalOffsetX);
-
- /// 3、计算 indicatorView 新的 frame
- self.indicatorView.SG_x = originalBtnIndicatorX + offsetX;
-
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + originalBtnTextWidth + distance;
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- CGFloat moveTotalX = targetBtn.SG_origin.x - originalBtn.SG_origin.x;
- CGFloat moveX = moveTotalX * progress;
- self.indicatorView.SG_centerX = originalBtn.SG_centerX + moveX;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- }
- }
- #pragma mark - - - SGPageTitleView 滚动样式下指示器默认滚动样式(SGIndicatorScrollStyleDefault)
- - (void)P_indicatorScrollStyleDefaultWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
- /// 改变按钮的选择状态
- if (progress >= 0.8) { /// 此处取 >= 0.8 而不是 1.0 为的是防止用户滚动过快而按钮的选中状态并没有改变
- [self P_changeSelectedButton:targetBtn];
- }
-
- if (self.configure.indicatorStyle == SGIndicatorStyleDynamic) {
- NSInteger originalBtnTag = originalBtn.tag;
- NSInteger targetBtnTag = targetBtn.tag;
- if (originalBtnTag <= targetBtnTag) { // 往左滑
- // targetBtn 与 originalBtn 中心点之间的距离
- CGFloat btnCenterXDistance = targetBtn.SG_centerX - originalBtn.SG_centerX;
- if (progress <= 0.5) {
- self.indicatorView.SG_width = 2 * progress * btnCenterXDistance + self.configure.indicatorDynamicWidth;
- } else {
- CGFloat targetBtnX = CGRectGetMaxX(targetBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (targetBtn.SG_width - self.configure.indicatorDynamicWidth);
- self.indicatorView.SG_x = targetBtnX + 2 * (progress - 1) * btnCenterXDistance;
- self.indicatorView.SG_width = 2 * (1 - progress) * btnCenterXDistance + self.configure.indicatorDynamicWidth;
- }
- } else {
- // originalBtn 与 targetBtn 中心点之间的距离
- CGFloat btnCenterXDistance = originalBtn.SG_centerX - targetBtn.SG_centerX;
- if (progress <= 0.5) {
- CGFloat originalBtnX = CGRectGetMaxX(originalBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (originalBtn.SG_width - self.configure.indicatorDynamicWidth);
- self.indicatorView.SG_x = originalBtnX - 2 * progress * btnCenterXDistance;
- self.indicatorView.SG_width = 2 * progress * btnCenterXDistance + self.configure.indicatorDynamicWidth;
- } else {
- CGFloat targetBtnX = CGRectGetMaxX(targetBtn.frame) - self.configure.indicatorDynamicWidth - 0.5 * (targetBtn.SG_width - self.configure.indicatorDynamicWidth);
- self.indicatorView.SG_x = targetBtnX; // 这句代码必须写,防止滚动结束之后指示器位置存在偏差,这里的偏差是由于 progress >= 0.8 导致的
- self.indicatorView.SG_width = 2 * (1 - progress) * btnCenterXDistance + self.configure.indicatorDynamicWidth;
- }
- }
-
- } else if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- CGFloat targetBtnIndicatorX = CGRectGetMaxX(targetBtn.frame) - 0.5 * (targetBtn.SG_width - self.configure.indicatorFixedWidth) - self.configure.indicatorFixedWidth;
- CGFloat originalBtnIndicatorX = CGRectGetMaxX(originalBtn.frame) - self.configure.indicatorFixedWidth - 0.5 * (originalBtn.SG_width - self.configure.indicatorFixedWidth);
- CGFloat totalOffsetX = targetBtnIndicatorX - originalBtnIndicatorX;
- CGFloat offsetX = totalOffsetX * progress;
- self.indicatorView.SG_x = originalBtnIndicatorX + offsetX;
-
- } else {
- // 1、计算 targetBtn/originalBtn 之间的 x 差值
- CGFloat totalOffsetX = targetBtn.SG_origin.x - originalBtn.SG_origin.x;
- // 2、计算 targetBtn/originalBtn 之间的差值
- CGFloat totalDistance = CGRectGetMaxX(targetBtn.frame) - CGRectGetMaxX(originalBtn.frame);
- /// 计算 indicatorView 滚动时 x 的偏移量
- CGFloat offsetX = 0.0;
- /// 计算 indicatorView 滚动时宽度的偏移量
- CGFloat distance = 0.0;
-
- CGFloat targetBtnTextWidth = [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + targetBtnTextWidth;
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- offsetX = totalOffsetX * progress;
- distance = progress * (totalDistance - totalOffsetX);
- self.indicatorView.SG_x = originalBtn.SG_origin.x + offsetX;
- self.indicatorView.SG_width = originalBtn.SG_width + distance;
- } else {
- offsetX = totalOffsetX * progress + 0.5 * self.configure.spacingBetweenButtons - 0.5 * self.configure.indicatorAdditionalWidth;
- distance = progress * (totalDistance - totalOffsetX) - self.configure.spacingBetweenButtons;
- /// 计算 indicatorView 新的 frame
- self.indicatorView.SG_x = originalBtn.SG_origin.x + offsetX;
- self.indicatorView.SG_width = originalBtn.SG_width + distance + self.configure.indicatorAdditionalWidth;
- }
- }
- }
- #pragma mark - - - SGPageTitleView 静止样式下指示器 SGIndicatorScrollStyleHalf 和 SGIndicatorScrollStyleEnd 滚动样式
- - (void)P_smallIndicatorScrollStyleHalfEndWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
- if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleHalf) {
- if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- if (progress >= 0.5) {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- return;
- }
-
- /// 指示器默认样式以及遮盖样式处理
- if (progress >= 0.5) {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- self.indicatorView.SG_width = targetBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- self.indicatorView.SG_width = originalBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- return;
- }
- /// 滚动内容结束指示器处理 ____ 指示器默认样式以及遮盖样式处理
- if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- if (progress == 1.0) {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- return;
- }
-
- if (progress == 1.0) {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- self.indicatorView.SG_width = targetBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- self.indicatorView.SG_width = originalBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- }
- #pragma mark - - - SGPageTitleView 滚动样式下指示器 SGIndicatorScrollStyleHalf 和 SGIndicatorScrollStyleEnd 滚动样式
- - (void)P_indicatorScrollStyleHalfEndWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
- if (self.configure.indicatorScrollStyle == SGIndicatorScrollStyleHalf) {
- if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- if (progress >= 0.5) {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- return;
- }
-
- /// 指示器默认样式以及遮盖样式处理
- if (progress >= 0.5) {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- self.indicatorView.SG_width = targetBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= originalBtn.SG_width) {
- self.indicatorView.SG_width = originalBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- return;
- }
- /// 滚动内容结束指示器处理 ____ 指示器默认样式以及遮盖样式处理
- if (self.configure.indicatorStyle == SGIndicatorStyleFixed) {
- if (progress == 1.0) {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- return;
- }
-
- if (progress == 1.0) {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:targetBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= targetBtn.SG_width) {
- self.indicatorView.SG_width = targetBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = targetBtn.SG_centerX;
- [self P_changeSelectedButton:targetBtn];
- }];
- } else {
- CGFloat tempIndicatorWidth = self.configure.indicatorAdditionalWidth + [self SG_widthWithString:originalBtn.currentTitle font:self.configure.titleFont];
- [UIView animateWithDuration:self.configure.indicatorAnimationTime animations:^{
- if (tempIndicatorWidth >= originalBtn.SG_width) {
- self.indicatorView.SG_width = originalBtn.SG_width;
- } else {
- self.indicatorView.SG_width = tempIndicatorWidth;
- }
- self.indicatorView.SG_centerX = originalBtn.SG_centerX;
- [self P_changeSelectedButton:originalBtn];
- }];
- }
- }
- #pragma mark - - - 颜色渐变方法抽取
- - (void)P_isTitleGradientEffectWithProgress:(CGFloat)progress originalBtn:(UIButton *)originalBtn targetBtn:(UIButton *)targetBtn {
- // 获取 targetProgress
- CGFloat targetProgress = progress;
- // 获取 originalProgress
- CGFloat originalProgress = 1 - targetProgress;
-
- CGFloat r = self.endR - self.startR;
- CGFloat g = self.endG - self.startG;
- CGFloat b = self.endB - self.startB;
- UIColor *originalColor = [UIColor colorWithRed:self.startR + r * originalProgress green:self.startG + g * originalProgress blue:self.startB + b * originalProgress alpha:1];
- UIColor *targetColor = [UIColor colorWithRed:self.startR + r * targetProgress green:self.startG + g * targetProgress blue:self.startB + b * targetProgress alpha:1];
-
- // 设置文字颜色渐变
- originalBtn.titleLabel.textColor = originalColor;
- targetBtn.titleLabel.textColor = targetColor;
- }
- #pragma mark - - - set
- - (void)setIsNeedBounces:(BOOL)isNeedBounces {
- _isNeedBounces = isNeedBounces;
- if (isNeedBounces == NO) {
- self.scrollView.bounces = NO;
- }
- }
- - (void)setSelectedIndex:(NSInteger)selectedIndex {
- _selectedIndex = selectedIndex;
-
- if (selectedIndex) {
- _selectedIndex = selectedIndex;
- }
- }
- - (void)setResetSelectedIndex:(NSInteger)resetSelectedIndex {
- _resetSelectedIndex = resetSelectedIndex;
- [self P_btn_action:self.btnMArr[resetSelectedIndex]];
- }
- - (void)setNewSelectedIndex:(NSInteger)newSelectedIndex {
- _newSelectedIndex = newSelectedIndex;
- [self c_btn_action:self.btnMArr[newSelectedIndex]];
- }
- - (void)setIsTitleGradientEffect:(BOOL)isTitleGradientEffect {
- _isTitleGradientEffect = isTitleGradientEffect;
- }
- - (void)setIsOpenTitleTextZoom:(BOOL)isOpenTitleTextZoom {
- _isOpenTitleTextZoom = isOpenTitleTextZoom;
- }
- - (void)setTitleTextScaling:(CGFloat)titleTextScaling {
- _titleTextScaling = titleTextScaling;
-
- if (titleTextScaling) {
- if (titleTextScaling >= 0.3) {
- _titleTextScaling = 0.3;
- } else {
- _titleTextScaling = 0.1;
- }
- }
- }
- - (void)setIsShowIndicator:(BOOL)isShowIndicator {
- _isShowIndicator = isShowIndicator;
- if (isShowIndicator == NO) {
- [self.indicatorView removeFromSuperview];
- self.indicatorView = nil;
- }
- }
- - (void)setIsShowBottomSeparator:(BOOL)isShowBottomSeparator {
- _isShowBottomSeparator = isShowBottomSeparator;
- if (isShowBottomSeparator) {
-
- } else {
- [self.bottomSeparator removeFromSuperview];
- self.bottomSeparator = nil;
- }
- }
- #pragma mark - - - 颜色设置的计算
- /// 开始颜色设置
- - (void)setupStartColor:(UIColor *)color {
- CGFloat components[3];
- [self getRGBComponents:components forColor:color];
- self.startR = components[0];
- self.startG = components[1];
- self.startB = components[2];
- }
- /// 结束颜色设置
- - (void)setupEndColor:(UIColor *)color {
- CGFloat components[3];
- [self getRGBComponents:components forColor:color];
- self.endR = components[0];
- self.endG = components[1];
- self.endB = components[2];
- }
- /**
- * 指定颜色,获取颜色的RGB值
- *
- * @param components RGB数组
- * @param color 颜色
- */
- - (void)getRGBComponents:(CGFloat [3])components forColor:(UIColor *)color {
- CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
- unsigned char resultingPixel[4];
- CGContextRef context = CGBitmapContextCreate(&resultingPixel, 1, 1, 8, 4, rgbColorSpace, 1);
- CGContextSetFillColorWithColor(context, [color CGColor]);
- CGContextFillRect(context, CGRectMake(0, 0, 1, 1));
- CGContextRelease(context);
- CGColorSpaceRelease(rgbColorSpace);
- for (int component = 0; component < 3; component++) {
- components[component] = resultingPixel[component] / 255.0f;
- }
- }
- @end
|