MLMSegmentHead.m 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. //
  2. // MLMSegmentHead.m
  3. // MLMSegmentPage
  4. //
  5. // Created by my on 16/11/4.
  6. // Copyright © 2016年 my. All rights reserved.
  7. //
  8. #import "MLMSegmentHead.h"
  9. #import "SegmentPageHead.h"
  10. #define SCROLL_WIDTH (self.width - _moreButton_width)
  11. #define SCROLL_HEIGHT (self.height - _bottomLineHeight)
  12. #define CURRENT_WIDTH(s) [titleWidthArray[s] floatValue]
  13. static CGFloat arrow_H = 6;//箭头高
  14. static CGFloat arrow_W = 18;//箭头宽
  15. static CGFloat animation_time = .3;
  16. @interface MLMSegmentHead ()
  17. /*------------其他设置------------*/
  18. /**
  19. * MLMSegmentHeadStyle
  20. */
  21. @property (nonatomic, assign) MLMSegmentHeadStyle headStyle;
  22. /**
  23. * MLMSegmentHeadStyle
  24. */
  25. @property (nonatomic, assign) MLMSegmentLayoutStyle layoutStyle;
  26. @end
  27. @implementation MLMSegmentHead
  28. {
  29. NSMutableArray *titlesArray;///标题数组
  30. UIScrollView *titlesScroll;
  31. NSMutableArray *buttonArray;//按钮数组
  32. NSMutableArray *backImgArray;//背景图数组
  33. UIView *lineView;//下划线view
  34. CAShapeLayer *arrow_layer;//箭头layer
  35. UIView *slideView;//滑块View
  36. UIScrollView *slideScroll;
  37. UIView *bottomLineView;//分割线
  38. NSInteger currentIndex;//当前选中的按钮
  39. //在与外侧scroll关联时,动画结束之后将其设置为NO
  40. BOOL isSelected;//区分点击还是滑动
  41. //button宽度的数组,总宽度
  42. NSMutableArray *titleWidthArray;
  43. CGFloat sum_width;
  44. //用来判断向左向右
  45. CGFloat endScale;
  46. }
  47. #pragma mark - initMethod
  48. - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles {
  49. return [self initWithFrame:frame titles:titles headStyle:SegmentHeadStyleDefault];
  50. }
  51. - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles headStyle:(MLMSegmentHeadStyle)style {
  52. return [self initWithFrame:frame titles:titles headStyle:style layoutStyle:MLMSegmentLayoutDefault];
  53. }
  54. - (instancetype)initWithFrame:(CGRect)frame titles:(NSArray *)titles headStyle:(MLMSegmentHeadStyle)style layoutStyle:(MLMSegmentLayoutStyle)layout {
  55. if (self = [super initWithFrame:frame]) {
  56. _headStyle = style;
  57. _layoutStyle = layout;
  58. titlesArray = [titles mutableCopy];
  59. [self initCustom];
  60. }
  61. return self;
  62. }
  63. #pragma mark - custom init
  64. - (void)initCustom {
  65. _headColor = [UIColor whiteColor];
  66. _selectColor = [UIColor blackColor];
  67. _deSelectColor = [UIColor lightGrayColor];
  68. _moreButton_width = 0;
  69. buttonArray = [NSMutableArray array];
  70. backImgArray = [NSMutableArray array];
  71. _showIndex = 0;
  72. _fontSize = 13;
  73. _fontScale = 1;
  74. _singleW_Add = 20;
  75. _lineColor = _selectColor;
  76. _lineHeight = 2.5;
  77. _lineScale = 1;
  78. _isNearLine = YES;
  79. _arrowColor = _selectColor;
  80. _slideHeight = SCROLL_HEIGHT;
  81. _slideColor = _deSelectColor;
  82. _slideCorner = _slideHeight/2;
  83. _slideScale = 1;
  84. _maxTitles = 5.0;
  85. _bottomLineColor = [UIColor grayColor];
  86. _bottomLineHeight = 1;
  87. }
  88. - (void)changeTitle:(NSArray *)titles {
  89. titlesArray = [titles mutableCopy];
  90. [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
  91. [self defaultAndCreateView];
  92. }
  93. #pragma mark - layout
  94. - (void)defaultAndCreateView {
  95. if (!titleWidthArray) {
  96. titleWidthArray = [NSMutableArray arrayWithCapacity:titlesArray.count];
  97. }
  98. [titleWidthArray removeAllObjects];
  99. _maxTitles = _maxTitles>titlesArray.count?titlesArray.count:_maxTitles;
  100. [self titlesWidth];
  101. if (_equalSize) {
  102. self.width = sum_width+_moreButton_width;
  103. if (titlesScroll) {
  104. titlesScroll.width = SCREEN_WIDTH;
  105. }
  106. if (slideScroll) {
  107. slideScroll.width = SCREEN_WIDTH;
  108. }
  109. }
  110. //判断总宽度
  111. if (sum_width > SCROLL_WIDTH && _layoutStyle== MLMSegmentLayoutCenter) {
  112. _layoutStyle = MLMSegmentLayoutLeft;
  113. }
  114. _showIndex = MIN(titlesArray.count-1, MAX(0, _showIndex));
  115. [self createView];
  116. if (_showIndex != 0) {
  117. currentIndex = _showIndex;
  118. [self changeContentOffset];
  119. [self changeBtnFrom:0 to:currentIndex];
  120. }
  121. }
  122. #pragma mark - 根据文字计算宽度
  123. - (void)titlesWidth {
  124. sum_width = 0;
  125. CGFloat width = SCROLL_WIDTH/_maxTitles;
  126. for (NSString *title in titlesArray) {
  127. if (_layoutStyle != MLMSegmentLayoutDefault) {
  128. width = [self titleWidth:title];
  129. }
  130. [titleWidthArray addObject:@(width)];
  131. sum_width += width;
  132. }
  133. }
  134. - (CGFloat)titleWidth:(NSString *)title {
  135. CGFloat sys_font = _fontScale>1?_fontSize*_fontScale:_fontSize;
  136. return [title boundingRectWithSize:CGSizeMake(MAXFLOAT, CGRectGetHeight(self.frame)) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName : Font_B(sys_font)} context:nil].size.width + _singleW_Add;
  137. }
  138. //#pragma mark - 添加按钮
  139. //- (void)addMoreTitles:(NSArray *)moreTitles {
  140. // if (_layoutStyle == MLMSegmentLayoutCenter) {
  141. // return;
  142. // }
  143. //
  144. // CGFloat start_x = sum_width;
  145. // CGFloat start_index = titleWidthArray.count;
  146. //
  147. // //添加到数组,并计算宽度
  148. // for (NSInteger i = 0; i < moreTitles.count; i ++) {
  149. // NSString *title = moreTitles[i];
  150. // CGFloat width = [self titleWidth:title];
  151. // [titleWidthArray addObject:@(width)];
  152. // sum_width += width;
  153. //
  154. // [titlesArray addObject:title];
  155. // }
  156. //
  157. // [self createBtn:titlesArray addScroll:titlesScroll startX:start_x start_index:start_index];
  158. // if (_headStyle == SegmentHeadStyleSlide) {
  159. // [self createBtn:titlesArray addScroll:slideScroll startX:start_x start_index:start_index];
  160. // }
  161. //
  162. //
  163. // [self setSelectIndex:currentIndex];
  164. //}
  165. #pragma mark - create View
  166. - (void)createView {
  167. _fontScale = _headStyle==SegmentHeadStyleSlide?1:_fontScale;
  168. titlesScroll = [self customScroll];
  169. [self scrollViewSubviews:titlesScroll];
  170. [self addSubview:titlesScroll];
  171. if (_moreButton_width != 0) {
  172. _moreButton = [[UIView alloc] init];
  173. _moreButton.frame = CGRectMake(CGRectGetMaxX(titlesScroll.frame), 0, _moreButton_width, titlesScroll.height);
  174. [self addSubview:_moreButton];
  175. }
  176. if (_bottomLineHeight) {
  177. bottomLineView = [self bottomLineView];
  178. [self addSubview:bottomLineView];
  179. }
  180. switch (_headStyle) {
  181. case SegmentHeadStyleLine:
  182. {
  183. lineView = [self lineView];
  184. [titlesScroll addSubview:lineView];
  185. }
  186. break;
  187. case SegmentHeadStyleArrow:
  188. {
  189. _lineHeight = arrow_H;
  190. _lineScale = 1;
  191. lineView = [self lineView];
  192. lineView.backgroundColor = [UIColor clearColor];
  193. [titlesScroll addSubview:lineView];
  194. //arrow
  195. [self drawArrowLayer];
  196. arrow_layer.position = CGPointMake(lineView.width/2, lineView.height/2);
  197. [lineView.layer addSublayer:arrow_layer];
  198. }
  199. break;
  200. case SegmentHeadStyleSlide:
  201. {
  202. if (self.slideDeSelectColor) {
  203. // slide背景
  204. [self createSlideBackgroundView];
  205. }
  206. slideView = [self slideView];
  207. [titlesScroll addSubview:slideView];
  208. }
  209. break;
  210. default:
  211. break;
  212. }
  213. }
  214. #pragma mark - drow arrow
  215. - (void)drawArrowLayer {
  216. arrow_layer = [[CAShapeLayer alloc] init];
  217. arrow_layer.bounds = CGRectMake(0, 0, arrow_W, arrow_H);
  218. [arrow_layer setFillColor:_arrowColor.CGColor];
  219. UIBezierPath *arrowPath = [UIBezierPath bezierPath];
  220. [arrowPath moveToPoint:CGPointMake(arrow_W/2, 0)];
  221. [arrowPath addLineToPoint:CGPointMake(arrow_W, arrow_H)];
  222. [arrowPath addLineToPoint:CGPointMake(0, arrow_H)];
  223. [arrowPath closePath];
  224. arrow_layer.path = arrowPath.CGPath;
  225. }
  226. #pragma mark - create customScroll
  227. - (UIScrollView *)customScroll {
  228. if (!titlesArray) {
  229. return nil;
  230. }
  231. UIScrollView *scroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, SCROLL_WIDTH, SCROLL_HEIGHT)];
  232. scroll.contentSize = CGSizeMake(MAX(SCROLL_WIDTH, sum_width), SCROLL_HEIGHT);
  233. scroll.backgroundColor = _headColor;
  234. scroll.showsVerticalScrollIndicator = NO;
  235. scroll.showsHorizontalScrollIndicator = NO;
  236. scroll.bounces = NO;
  237. return scroll;
  238. }
  239. #pragma mark - titlesScroll subviews - yes or slideScroll subviews - no
  240. - (void)scrollViewSubviews:(UIScrollView*)scroll {
  241. BOOL titles = [scroll isEqual:titlesScroll];
  242. CGFloat start_x = 0;
  243. if (_layoutStyle == MLMSegmentLayoutCenter) {
  244. //计算布局的起点
  245. start_x = SCROLL_WIDTH/2;
  246. for (NSInteger i = 0; i < titleWidthArray.count/2; i ++) {
  247. start_x -= CURRENT_WIDTH(i);
  248. }
  249. if (titlesArray.count%2 != 0) {
  250. start_x -= CURRENT_WIDTH(titleWidthArray.count/2)/2;
  251. }
  252. }
  253. [self createBtn:titlesArray addScroll:scroll startX:start_x start_index:0];
  254. if (titles && _headStyle != SegmentHeadStyleSlide) {
  255. UIButton *curBtn = buttonArray[_showIndex];
  256. if (_fontScale != 1) {
  257. curBtn.titleLabel.font = Font_B(_fontSize*_fontScale);
  258. }
  259. [curBtn setTintColor:_selectColor];
  260. }
  261. }
  262. #pragma mark - createBtn
  263. - (void)createBtn:(NSArray *)titlesArr addScroll:(UIScrollView*)scroll startX:(CGFloat)start_x start_index:(NSInteger)start_index {
  264. BOOL titles = [scroll isEqual:titlesScroll];
  265. CGFloat width;
  266. for (NSInteger i = start_index; i < titlesArr.count; i ++) {
  267. width = CURRENT_WIDTH(i);
  268. UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
  269. [button setTitle:titlesArr[i] forState:UIControlStateNormal];
  270. button.titleLabel.font = Font_B(_fontSize);
  271. button.frame = CGRectMake(start_x, 0, width, SCROLL_HEIGHT);
  272. start_x += width;
  273. if (titles) {
  274. [button setTintColor:_deSelectColor];
  275. [button addTarget:self action:@selector(selectedHeadTitles:) forControlEvents:UIControlEventTouchUpInside];
  276. [buttonArray addObject:button];
  277. //
  278. UIImageView *imgV = [[UIImageView alloc] initWithFrame:button.frame];
  279. [scroll addSubview:imgV];
  280. [backImgArray addObject:imgV];
  281. } else {
  282. [button setTintColor:_selectColor];
  283. }
  284. [scroll addSubview:button];
  285. }
  286. scroll.contentSize = CGSizeMake(MAX(SCROLL_WIDTH, sum_width), SCROLL_HEIGHT);
  287. }
  288. - (void)setBackImages:(NSArray *)backImages {
  289. _backImages = backImages;
  290. NSInteger count = MIN(backImages.count, backImgArray.count);
  291. for (NSInteger i = 0; i < count; i ++) {
  292. UIImageView *imageV = backImgArray[i];
  293. [imageV setImage:backImages[i]];
  294. if (i == currentIndex) {
  295. imageV.alpha = 1;
  296. } else {
  297. imageV.alpha = 0;
  298. }
  299. }
  300. }
  301. #pragma mark - create Line
  302. - (UIImageView *)lineView {
  303. _lineScale = fabs(_lineScale)>1?1:fabs(_lineScale);
  304. CGFloat width = _lineWidth;
  305. if (_lineWidth == 0) {
  306. CGFloat line_w = CURRENT_WIDTH(currentIndex);
  307. width = line_w*_lineScale;
  308. }
  309. CGFloat sys_font = _fontScale>1?_fontSize*_fontScale:_fontSize;
  310. CGFloat lineY = (SCROLL_HEIGHT - Font(sys_font).lineHeight)/2 + Font(sys_font).lineHeight;
  311. if (self.isNearLine) {
  312. lineY = SCROLL_HEIGHT-_lineHeight;
  313. }
  314. UIImageView *line = [[UIImageView alloc] initWithFrame:CGRectMake(0, lineY, width, _lineHeight)];
  315. UIButton *current_btn = buttonArray[currentIndex];
  316. line.center = CGPointMake(current_btn.center.x, line.center.y);
  317. line.backgroundColor = _lineColor;
  318. if (_lineImage) {
  319. line.image = _lineImage;
  320. }
  321. [line addViewBorder:Color_Clear redian:2];
  322. return line;
  323. }
  324. #pragma mark - bottom Line
  325. - (UIView *)bottomLineView {
  326. UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, SCROLL_HEIGHT, self.width, _bottomLineHeight)];
  327. line.backgroundColor = _bottomLineColor;
  328. return line;
  329. }
  330. #pragma mark - create slide
  331. - (void)createSlideBackgroundView {
  332. for (UIButton *btn in buttonArray) {
  333. UIImageView *slideBackground = [[UIImageView alloc] initWithFrame:CGRectMake(0, (SCROLL_HEIGHT-_slideHeight)/2, btn.width*_slideScale, _slideHeight)];
  334. slideBackground.center = CGPointMake(btn.center.x, slideBackground.center.y);
  335. slideBackground.clipsToBounds = YES;
  336. slideBackground.layer.cornerRadius = MIN(_slideCorner, _slideHeight/2);
  337. slideBackground.backgroundColor = self.slideDeSelectColor;
  338. [titlesScroll addSubview:slideBackground];
  339. [titlesScroll sendSubviewToBack:slideBackground];
  340. }
  341. }
  342. - (UIImageView *)slideView {
  343. CGFloat slide_w = CURRENT_WIDTH(currentIndex);
  344. UIImageView *slide = [[UIImageView alloc] initWithFrame:CGRectMake(0, (SCROLL_HEIGHT-_slideHeight)/2, slide_w*_slideScale, _slideHeight)];
  345. UIButton *current_btn = buttonArray[currentIndex];
  346. slide.center = CGPointMake(current_btn.center.x, slide.center.y);
  347. slide.clipsToBounds = YES;
  348. slide.layer.cornerRadius = MIN(_slideCorner, _slideHeight/2);
  349. slide.backgroundColor = _slideColor;
  350. if (_slideImage) {
  351. slide.image = _slideImage;
  352. }
  353. slideScroll = [self customScroll];
  354. [self scrollViewSubviews:slideScroll];
  355. slideScroll.userInteractionEnabled = NO;
  356. slideScroll.backgroundColor = [UIColor clearColor];
  357. CGRect convertRect = [slide convertRect:titlesScroll.frame fromView:titlesScroll.superview];
  358. slideScroll.frame = CGRectMake(convertRect.origin.x, -(SCROLL_HEIGHT - _slideHeight)/2, SCROLL_WIDTH, SCROLL_HEIGHT);
  359. [slide addSubview:slideScroll];
  360. return slide;
  361. }
  362. #pragma mark - button Action
  363. - (void)selectedHeadTitles:(UIButton *)button {
  364. NSInteger selectIndex = [buttonArray indexOfObject:button];
  365. [self changeIndex:selectIndex completion:YES];
  366. }
  367. #pragma mark - 点击结束
  368. - (void)animationEnd {
  369. isSelected = NO;
  370. }
  371. #pragma mark - set index
  372. - (void)setSelectIndex:(NSInteger)index {
  373. // if (index == currentIndex) {
  374. // return;
  375. // }
  376. // //before
  377. // NSInteger before = currentIndex;
  378. // currentIndex = index;
  379. // [self changeContentOffset];
  380. // //select
  381. // [UIView animateWithDuration:animation_time animations:^{
  382. // [self changeBtnFrom:before to:currentIndex];
  383. // } completion:^(BOOL finished) {
  384. // }];
  385. // isSelected = YES;
  386. // if ([self.delegate respondsToSelector:@selector(didSelectedIndex:)]) {
  387. // [self.delegate didSelectedIndex:currentIndex];
  388. // } else if (self.selectedIndex) {
  389. // self.selectedIndex(currentIndex);
  390. // }
  391. [self changeIndex:index completion:NO];
  392. }
  393. - (void)changeIndex:(NSInteger)index completion:(BOOL)completion {
  394. // if (index == currentIndex) {
  395. // return;
  396. // }
  397. //before
  398. NSInteger before = currentIndex;
  399. currentIndex = index;
  400. [self changeContentOffset];
  401. //select
  402. [UIView animateWithDuration:animation_time animations:^{
  403. [self changeBtnFrom:before to:self->currentIndex];
  404. } completion:^(BOOL finished) {
  405. }];
  406. isSelected = YES;
  407. if (completion) {
  408. if ([self.delegate respondsToSelector:@selector(didSelectedIndex:)]) {
  409. [self.delegate didSelectedIndex:currentIndex];
  410. } else if (self.selectedIndex) {
  411. self.selectedIndex(currentIndex);
  412. }
  413. }
  414. }
  415. - (void)changeContentOffset {
  416. if (sum_width > SCROLL_WIDTH) {
  417. UIButton *currentBtn = buttonArray[currentIndex];
  418. if (currentBtn.center.x<SCROLL_WIDTH/2) {
  419. [titlesScroll setContentOffset:CGPointMake(0, 0) animated:YES];
  420. } else if (currentBtn.center.x > (sum_width-SCROLL_WIDTH/2)) {
  421. [titlesScroll setContentOffset:CGPointMake(sum_width-SCROLL_WIDTH, 0) animated:YES];
  422. } else {
  423. [titlesScroll setContentOffset:CGPointMake(currentBtn.center.x - SCROLL_WIDTH/2, 0) animated:YES];
  424. }
  425. }
  426. }
  427. - (void)changeBtnFrom:(NSInteger)from to:(NSInteger)to {
  428. UIButton *before_btn = buttonArray[from];
  429. UIButton *select_btn = buttonArray[to];
  430. if (_headStyle != SegmentHeadStyleSlide) {
  431. [before_btn setTintColor:_deSelectColor];
  432. [select_btn setTintColor:_selectColor];
  433. }
  434. if (_fontScale) {
  435. before_btn.titleLabel.font = Font_B(_fontSize);
  436. select_btn.titleLabel.font = Font_B(_fontSize*_fontScale);
  437. }
  438. if (lineView) {
  439. CGFloat width = _lineWidth;
  440. if (_lineWidth == 0) {
  441. width = select_btn.width*_lineScale;
  442. }
  443. lineView.width = width;
  444. lineView.center = CGPointMake(select_btn.center.x, lineView.center.y);
  445. }
  446. if (arrow_layer) {
  447. arrow_layer.position = CGPointMake(lineView.width/2, lineView.height/2);
  448. }
  449. if (slideView) {
  450. //slide位置变化
  451. slideView.width = select_btn.width*_slideScale;
  452. slideView.center = CGPointMake(select_btn.center.x, slideView.center.y);
  453. //偏移
  454. CGRect convertRect = [slideView convertRect:titlesScroll.frame fromView:titlesScroll];
  455. slideScroll.frame = CGRectMake(convertRect.origin.x, convertRect.origin.y, slideScroll.contentSize.width, slideScroll.contentSize.height);
  456. }
  457. if (_hadBackImg) {
  458. UIImageView *before_img = backImgArray[from];
  459. UIImageView *select_img = backImgArray[to];
  460. before_img.alpha = 0;
  461. select_img.alpha = 1;
  462. }
  463. }
  464. #pragma mark - animation
  465. //外部关联的scrollView变化
  466. - (void)changePointScale:(CGFloat)scale {
  467. if (isSelected) {
  468. return;
  469. }
  470. if (scale<0) {
  471. return;
  472. }
  473. //区分向左 还是向右
  474. BOOL left = endScale > scale;
  475. endScale = scale;
  476. //1.将scale变为对应titleScroll的titleScale
  477. //每个view所占的百分比
  478. CGFloat per_view = 1.0/(CGFloat)titlesArray.count;
  479. //下标
  480. NSInteger changeIndex = scale/per_view + (left?1:0);
  481. NSInteger nextIndex = changeIndex + (left?-1:1);
  482. //超出范围
  483. if (nextIndex >= titlesArray.count || changeIndex >= titlesArray.count) {
  484. return;
  485. }
  486. //currentbtn
  487. UIButton *currentBtn = buttonArray[changeIndex];
  488. UIButton *nextBtn = buttonArray[nextIndex];
  489. //startscla
  490. CGFloat start_scale = 0;
  491. for (NSInteger i = 0; i < nextIndex; i++) {
  492. start_scale += CURRENT_WIDTH(i)/sum_width;
  493. }
  494. //滑动选中位置所占的相对百分比
  495. CGFloat current_title_Scale = CURRENT_WIDTH(changeIndex)/sum_width;
  496. //单个view偏移的百分比
  497. CGFloat single_offset_scale = (scale - per_view*changeIndex)/per_view;
  498. //转换成对应title的百分比
  499. CGFloat titleScale = single_offset_scale * current_title_Scale + start_scale;
  500. //变化的百分比
  501. CGFloat change_scale = (left?-1:1)*(titleScale - start_scale)/current_title_Scale;
  502. switch (_headStyle) {
  503. case SegmentHeadStyleDefault:
  504. case SegmentHeadStyleLine:
  505. case SegmentHeadStyleArrow:
  506. {
  507. if (lineView) {
  508. //lineView位置变化
  509. CGFloat width = _lineWidth;
  510. if (_lineWidth == 0) {
  511. lineView.width = [self widthChangeCurWidth:CURRENT_WIDTH(changeIndex) nextWidth:CURRENT_WIDTH(nextIndex) changeScale:change_scale endScale:_lineScale];
  512. }else {
  513. lineView.width = width;
  514. }
  515. CGFloat center_x = [self centerChanegCurBtn:currentBtn nextBtn:nextBtn changeScale:change_scale];
  516. lineView.center = CGPointMake(center_x, lineView.center.y);
  517. }
  518. if (arrow_layer) {
  519. arrow_layer.position = CGPointMake(lineView.width/2, lineView.height/2);
  520. }
  521. //颜色变化
  522. [self colorChangeCurBtn:currentBtn nextBtn:nextBtn changeScale:change_scale];
  523. //字体大小变化
  524. [self fontChangeCurBtn:currentBtn nextBtn:nextBtn changeScale:change_scale];
  525. //背景图片
  526. if (_hadBackImg) {
  527. UIImageView *current_img = backImgArray[changeIndex];
  528. UIImageView *next_img = backImgArray[nextIndex];
  529. [self backImgCurImg:current_img nextImg:next_img changeScale:change_scale];
  530. }
  531. }
  532. break;
  533. case SegmentHeadStyleSlide:
  534. {
  535. //slide位置变化
  536. slideView.width = [self widthChangeCurWidth:CURRENT_WIDTH(changeIndex) nextWidth:CURRENT_WIDTH(nextIndex) changeScale:change_scale endScale:_slideScale];
  537. CGFloat center_x = [self centerChanegCurBtn:currentBtn nextBtn:nextBtn changeScale:change_scale];
  538. slideView.center = CGPointMake(center_x, slideView.center.y);
  539. //偏移
  540. CGRect convertRect = [slideView convertRect:titlesScroll.frame fromView:titlesScroll];
  541. slideScroll.frame = CGRectMake(convertRect.origin.x, convertRect.origin.y, slideScroll.contentSize.width, slideScroll.contentSize.height);
  542. }
  543. break;
  544. default:
  545. break;
  546. }
  547. }
  548. #pragma mark - 长度变化
  549. - (CGFloat)widthChangeCurWidth:(CGFloat)curWidth nextWidth:(CGFloat)nextWidth changeScale:(CGFloat)changeScale endScale:(CGFloat)endscale{
  550. //改变的宽度
  551. CGFloat change_width = curWidth - nextWidth;
  552. //宽度变化
  553. CGFloat width = curWidth*endscale - changeScale * change_width;
  554. return width;
  555. }
  556. #pragma mark - 中心位置的变化
  557. - (CGFloat)centerChanegCurBtn:(UIButton *)curBtn nextBtn:(UIButton *)nextBtn changeScale:(CGFloat)changeScale {
  558. //lineView改变的中心
  559. CGFloat change_center = nextBtn.center.x - curBtn.center.x;
  560. //lineView位置变化
  561. CGFloat center_x = curBtn.center.x + changeScale * change_center;
  562. return center_x;
  563. }
  564. #pragma mark - 字体大小变化
  565. - (void)fontChangeCurBtn:(UIButton *)curBtn nextBtn:(UIButton *)nextBtn changeScale:(CGFloat)changeScale{
  566. //button字体改变的大小
  567. CGFloat btn_font_change = _fontSize*(_fontScale - 1);
  568. //大小变化
  569. CGFloat next_font = _fontSize + changeScale*btn_font_change;
  570. CGFloat cur_font = _fontSize*_fontScale - changeScale*btn_font_change;
  571. nextBtn.titleLabel.font = Font_B(next_font);
  572. curBtn.titleLabel.font = Font_B(cur_font);
  573. }
  574. #pragma mark - 颜色变化
  575. - (void)colorChangeCurBtn:(UIButton *)curBtn nextBtn:(UIButton *)nextBtn changeScale:(CGFloat)changeScale {
  576. //button选中颜色
  577. CGFloat sel_red;
  578. CGFloat sel_green;
  579. CGFloat sel_blue;
  580. CGFloat sel_alpha;
  581. //button未选中的颜色
  582. CGFloat de_sel_red;
  583. CGFloat de_sel_green;
  584. CGFloat de_sel_blue;
  585. CGFloat de_sel_alpha;
  586. if ([_selectColor getRed:&sel_red green:&sel_green blue:&sel_blue alpha:&sel_alpha] && [_deSelectColor getRed:&de_sel_red green:&de_sel_green blue:&de_sel_blue alpha:&de_sel_alpha]) {
  587. //颜色的变化的大小
  588. CGFloat red_changge = sel_red - de_sel_red;
  589. CGFloat green_changge = sel_green - de_sel_green;
  590. CGFloat blue_changge = sel_blue - de_sel_blue;
  591. CGFloat alpha_changge = sel_alpha - de_sel_alpha;
  592. //颜色变化
  593. [nextBtn setTintColor:[UIColor colorWithRed:de_sel_red + red_changge*changeScale
  594. green:de_sel_green + green_changge*changeScale
  595. blue:de_sel_blue + blue_changge*changeScale
  596. alpha:de_sel_alpha + alpha_changge*changeScale]];
  597. [curBtn setTintColor:[UIColor colorWithRed:sel_red - red_changge*changeScale
  598. green:sel_green - green_changge*changeScale
  599. blue:sel_blue - blue_changge*changeScale
  600. alpha:sel_alpha - alpha_changge*changeScale]];
  601. }
  602. }
  603. #pragma mark - 背景图渐变
  604. - (void)backImgCurImg:(UIImageView *)curback nextImg:(UIImageView *)nextback changeScale:(CGFloat)changeScale {
  605. //alpha变化
  606. CGFloat next_alpha = changeScale;
  607. CGFloat cur_alpha = 1 - changeScale;
  608. nextback.alpha = next_alpha>.8?1.:next_alpha;
  609. curback.alpha = cur_alpha<.2?0:cur_alpha;
  610. }
  611. #pragma mark - get sumWidth
  612. - (CGFloat)getSumWidth {
  613. return sum_width;
  614. }
  615. #pragma mark - lineView
  616. - (UIView *)getLineView {
  617. return lineView;
  618. }
  619. - (UIView *)getBottomLineView {
  620. return bottomLineView;
  621. }
  622. - (UIView *)getScrollLineView {
  623. if (_headStyle == SegmentHeadStyleLine) {
  624. return lineView;
  625. } else {
  626. return nil;
  627. }
  628. }
  629. #pragma mark - dealloc
  630. - (void)dealloc {
  631. arrow_layer.delegate = nil;
  632. [arrow_layer removeFromSuperlayer];
  633. arrow_layer = nil;
  634. }
  635. - (UIScrollView *)titlesScroll {
  636. return titlesScroll;
  637. }
  638. - (NSArray *)buttons {
  639. return buttonArray;
  640. }
  641. @end