TYTabPagerBarLayout.m 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. //
  2. // TYTabPagerBarLayout.m
  3. // TYPagerControllerDemo
  4. //
  5. // Created by tanyang on 2017/7/17.
  6. // Copyright © 2017年 tany. All rights reserved.
  7. //
  8. #import "TYTabPagerBarLayout.h"
  9. #import "TYTabPagerBar.h"
  10. @interface TYTabPagerBarLayout ()
  11. @property (nonatomic, weak) TYTabPagerBar *pagerTabBar;
  12. @property (nonatomic, assign) CGFloat selectFontScale;
  13. @end
  14. #define kUnderLineViewHeight 2
  15. @implementation TYTabPagerBarLayout
  16. - (instancetype)initWithPagerTabBar:(TYTabPagerBar *)pagerTabBar {
  17. if (self = [super init]) {
  18. _pagerTabBar = pagerTabBar;
  19. [self configurePropertys];
  20. self.barStyle = TYPagerBarStyleProgressElasticView;
  21. }
  22. return self;
  23. }
  24. - (void)configurePropertys {
  25. _cellSpacing = 2;
  26. _cellEdging = 3;
  27. _cellWidth = 0;
  28. _progressHorEdging = 6;
  29. _progressWidth = 0;
  30. _animateDuration = 0.25;
  31. _normalTextFont = [UIFont systemFontOfSize:13];
  32. _selectedTextFont = [UIFont systemFontOfSize:13];
  33. _normalTextColor = RGB_COLOR(@"#646464", 1);
  34. _selectedTextColor = [UIColor whiteColor];
  35. _textColorProgressEnable = YES;
  36. //_adjustContentCellsCenter = YES;
  37. }
  38. #pragma mark - geter setter
  39. - (void)setProgressRadius:(CGFloat)progressRadius {
  40. _progressRadius = progressRadius;
  41. _pagerTabBar.progressView.layer.cornerRadius = progressRadius;
  42. }
  43. - (void)setProgressBorderWidth:(CGFloat)progressBorderWidth {
  44. _progressBorderWidth = progressBorderWidth;
  45. _pagerTabBar.progressView.layer.borderWidth = progressBorderWidth;
  46. }
  47. - (void)setProgressBorderColor:(UIColor *)progressBorderColor {
  48. _progressBorderColor = progressBorderColor;
  49. if (!_progressColor) {
  50. _pagerTabBar.progressView.backgroundColor = [UIColor clearColor];
  51. }
  52. _pagerTabBar.progressView.layer.borderColor = progressBorderColor.CGColor;
  53. }
  54. - (void)setProgressColor:(UIColor *)progressColor {
  55. _progressColor = progressColor;
  56. _pagerTabBar.progressView.backgroundColor = progressColor;
  57. }
  58. - (void)setProgressHeight:(CGFloat)progressHeight {
  59. _progressHeight = progressHeight;
  60. CGRect frame = _pagerTabBar.progressView.frame;
  61. CGFloat height = CGRectGetHeight(_pagerTabBar.collectionView.frame);
  62. frame.origin.y = _barStyle == TYPagerBarStyleCoverView ? (height - _progressHeight)/2:(height - _progressHeight - _progressVerEdging);
  63. frame.size.height = progressHeight;
  64. _pagerTabBar.progressView.frame = frame;
  65. }
  66. - (UIEdgeInsets)sectionInset {
  67. if (!UIEdgeInsetsEqualToEdgeInsets(_sectionInset, UIEdgeInsetsZero) || _barStyle != TYPagerBarStyleCoverView) {
  68. return _sectionInset;
  69. }
  70. if (_barStyle == TYPagerBarStyleCoverView && _adjustContentCellsCenter) {
  71. return _sectionInset;
  72. }
  73. CGFloat horEdging = -_progressHorEdging+_cellSpacing;
  74. return UIEdgeInsetsMake(0, horEdging, 0, horEdging);
  75. }
  76. - (void)setAdjustContentCellsCenter:(BOOL)adjustContentCellsCenter {
  77. BOOL change = _adjustContentCellsCenter != adjustContentCellsCenter;
  78. _adjustContentCellsCenter = adjustContentCellsCenter;
  79. if (change && _pagerTabBar.superview) {
  80. [_pagerTabBar setNeedsLayout];
  81. }
  82. }
  83. - (void)setBarStyle:(TYPagerBarStyle)barStyle
  84. {
  85. if (barStyle == _barStyle) {
  86. return;
  87. }
  88. if (_barStyle == TYPagerBarStyleCoverView) {
  89. self.progressBorderWidth = 0;
  90. self.progressBorderColor = nil;
  91. }
  92. _barStyle = barStyle;
  93. switch (barStyle) {
  94. case TYPagerBarStyleProgressView:
  95. self.progressWidth = 0;
  96. self.progressHorEdging = 6;
  97. self.progressVerEdging = 0;
  98. self.progressHeight = kUnderLineViewHeight;
  99. break;
  100. case TYPagerBarStyleProgressBounceView:
  101. case TYPagerBarStyleProgressElasticView:
  102. self.progressWidth = 30;
  103. self.progressVerEdging = 0;
  104. self.progressHorEdging = 0;
  105. self.progressHeight = kUnderLineViewHeight;
  106. break;
  107. case TYPagerBarStyleCoverView:
  108. self.progressWidth = 0;
  109. self.progressHorEdging = -self.progressHeight/4;
  110. self.progressVerEdging = 3;
  111. break;
  112. default:
  113. break;
  114. }
  115. _pagerTabBar.progressView.hidden = barStyle == TYPagerBarStyleNoneView;
  116. if (barStyle == TYPagerBarStyleCoverView) {
  117. _progressRadius = 0;
  118. _pagerTabBar.progressView.layer.zPosition = -1;
  119. [_pagerTabBar.progressView removeFromSuperview];
  120. [_pagerTabBar.collectionView insertSubview: _pagerTabBar.progressView atIndex:0];
  121. }else {
  122. self.progressRadius = _progressHeight/2;
  123. if (_pagerTabBar.progressView.layer.zPosition == -1) {
  124. _pagerTabBar.progressView.layer.zPosition = 0;
  125. [_pagerTabBar.progressView removeFromSuperview];
  126. [_pagerTabBar.collectionView addSubview:_pagerTabBar.progressView];
  127. }
  128. }
  129. }
  130. #pragma mark - public
  131. - (void)layoutIfNeed {
  132. UICollectionViewFlowLayout *collectionLayout = (UICollectionViewFlowLayout *)_pagerTabBar.collectionView.collectionViewLayout;
  133. collectionLayout.minimumLineSpacing = _cellSpacing;
  134. collectionLayout.minimumInteritemSpacing = _cellSpacing;
  135. _selectFontScale = self.normalTextFont.pointSize/(self.selectedTextFont ? self.selectedTextFont.pointSize:self.normalTextFont.pointSize);
  136. collectionLayout.sectionInset = _sectionInset;
  137. }
  138. - (void)invalidateLayout {
  139. [_pagerTabBar.collectionView.collectionViewLayout invalidateLayout];
  140. }
  141. - (void)adjustContentCellsCenterInBar {
  142. if (!_adjustContentCellsCenter || !_pagerTabBar.superview) {
  143. return;
  144. }
  145. CGRect frame = self.pagerTabBar.collectionView.frame;
  146. if (CGRectIsEmpty(frame)) {
  147. return;
  148. }
  149. UICollectionViewFlowLayout *collectionLayout = (UICollectionViewFlowLayout *)_pagerTabBar.collectionView.collectionViewLayout;
  150. CGSize contentSize = collectionLayout.collectionViewContentSize;
  151. NSArray *layoutAttribulte = [collectionLayout layoutAttributesForElementsInRect:CGRectMake(0, 0, MAX(contentSize.width, CGRectGetWidth(frame)), MAX(contentSize.height,CGRectGetHeight(frame)))];
  152. if (layoutAttribulte.count == 0) {
  153. return;
  154. }
  155. UICollectionViewLayoutAttributes *firstAttribute = layoutAttribulte.firstObject;
  156. UICollectionViewLayoutAttributes *lastAttribute = layoutAttribulte.lastObject;
  157. CGFloat left = CGRectGetMinX(firstAttribute.frame);
  158. CGFloat right = CGRectGetMaxX(lastAttribute.frame);
  159. if (right - left > CGRectGetWidth(self.pagerTabBar.frame)) {
  160. return;
  161. }
  162. CGFloat sapce = (CGRectGetWidth(self.pagerTabBar.frame) - (right - left))/2;
  163. _sectionInset = UIEdgeInsetsMake(_sectionInset.top, sapce, _sectionInset.bottom, sapce);
  164. collectionLayout.sectionInset = _sectionInset;
  165. }
  166. - (CGRect)cellFrameWithIndex:(NSInteger)index {
  167. return [_pagerTabBar cellFrameWithIndex:index];
  168. }
  169. #pragma mark - cell
  170. - (void)transitionFromCell:(UICollectionViewCell<TYTabPagerBarCellProtocol> *)fromCell toCell:(UICollectionViewCell<TYTabPagerBarCellProtocol> *)toCell animate:(BOOL)animate {
  171. if (_pagerTabBar.countOfItems == 0) {
  172. return;
  173. }
  174. void (^animateBlock)() = ^{
  175. if (fromCell) {
  176. fromCell.titleLabel.font = _normalTextFont;
  177. fromCell.titleLabel.textColor = _normalTextColor;
  178. fromCell.transform = CGAffineTransformMakeScale(_selectFontScale, _selectFontScale);
  179. }
  180. if (toCell) {
  181. toCell.titleLabel.font = _normalTextFont;
  182. toCell.titleLabel.textColor = _selectedTextColor ? _selectedTextColor : _normalTextColor;
  183. toCell.transform = CGAffineTransformIdentity;
  184. }
  185. };
  186. if (animate) {
  187. [UIView animateWithDuration:_animateDuration animations:^{
  188. animateBlock();
  189. }];
  190. }else{
  191. animateBlock();
  192. }
  193. }
  194. - (void)transitionFromCell:(UICollectionViewCell<TYTabPagerBarCellProtocol> *)fromCell toCell:(UICollectionViewCell<TYTabPagerBarCellProtocol> *)toCell progress:(CGFloat)progress {
  195. if (_pagerTabBar.countOfItems == 0 || !_textColorProgressEnable) {
  196. return;
  197. }
  198. CGFloat currentTransform = (1.0 - _selectFontScale)*progress;
  199. fromCell.transform = CGAffineTransformMakeScale(1.0-currentTransform, 1.0-currentTransform);
  200. toCell.transform = CGAffineTransformMakeScale(_selectFontScale+currentTransform, _selectFontScale+currentTransform);
  201. if (_normalTextColor == _selectedTextColor || !_selectedTextColor) {
  202. return;
  203. }
  204. CGFloat narR=0,narG=0,narB=0,narA=1;
  205. [_normalTextColor getRed:&narR green:&narG blue:&narB alpha:&narA];
  206. CGFloat selR=0,selG=0,selB=0,selA=1;
  207. [_selectedTextColor getRed:&selR green:&selG blue:&selB alpha:&selA];
  208. CGFloat detalR = narR - selR ,detalG = narG - selG,detalB = narB - selB,detalA = narA - selA;
  209. fromCell.titleLabel.textColor = [UIColor colorWithRed:selR+detalR*progress green:selG+detalG*progress blue:selB+detalB*progress alpha:selA+detalA*progress];
  210. toCell.titleLabel.textColor = [UIColor colorWithRed:narR-detalR*progress green:narG-detalG*progress blue:narB-detalB*progress alpha:narA-detalA*progress];
  211. }
  212. #pragma mark - progress View
  213. // set up progress view frame
  214. - (void)setUnderLineFrameWithIndex:(NSInteger)index animated:(BOOL)animated
  215. {
  216. UIView *progressView = _pagerTabBar.progressView;
  217. if (progressView.isHidden || _pagerTabBar.countOfItems == 0) {
  218. return;
  219. }
  220. CGRect cellFrame = [self cellFrameWithIndex:index];
  221. CGFloat progressHorEdging = _progressWidth > 0 ? (cellFrame.size.width - _progressWidth)/2 : _progressHorEdging;
  222. CGFloat progressX = cellFrame.origin.x+progressHorEdging;
  223. CGFloat progressY = _barStyle == TYPagerBarStyleCoverView ? (cellFrame.size.height - _progressHeight)/2:(cellFrame.size.height - _progressHeight - _progressVerEdging);
  224. CGFloat width = cellFrame.size.width-2*progressHorEdging;
  225. if (animated) {
  226. [UIView animateWithDuration:_animateDuration animations:^{
  227. progressView.frame = CGRectMake(progressX, progressY, width, _progressHeight);
  228. }];
  229. }else {
  230. progressView.frame = CGRectMake(progressX, progressY, width, _progressHeight);
  231. }
  232. }
  233. - (void)setUnderLineFrameWithfromIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex progress:(CGFloat)progress
  234. {
  235. UIView *progressView = _pagerTabBar.progressView;
  236. if (progressView.isHidden || _pagerTabBar.countOfItems == 0) {
  237. return;
  238. }
  239. CGRect fromCellFrame = [self cellFrameWithIndex:fromIndex];
  240. CGRect toCellFrame = [self cellFrameWithIndex:toIndex];
  241. CGFloat progressFromEdging = _progressWidth > 0 ? (fromCellFrame.size.width - _progressWidth)/2 : _progressHorEdging;
  242. CGFloat progressToEdging = _progressWidth > 0 ? (toCellFrame.size.width - _progressWidth)/2 : _progressHorEdging;
  243. CGFloat progressY = _barStyle == TYPagerBarStyleCoverView ? (toCellFrame.size.height - _progressHeight)/2:(toCellFrame.size.height - _progressHeight - _progressVerEdging);
  244. CGFloat progressX = 0, width = 0;
  245. if (_barStyle == TYPagerBarStyleProgressBounceView) {
  246. if (fromCellFrame.origin.x < toCellFrame.origin.x) {
  247. if (progress <= 0.5) {
  248. progressX = fromCellFrame.origin.x + progressFromEdging;
  249. width = (toCellFrame.size.width-progressToEdging+progressFromEdging+_cellSpacing)*2*progress + fromCellFrame.size.width-2*progressFromEdging;
  250. }else {
  251. progressX = fromCellFrame.origin.x + progressFromEdging + (fromCellFrame.size.width-progressFromEdging+progressToEdging+_cellSpacing)*(progress-0.5)*2;
  252. width = CGRectGetMaxX(toCellFrame)-progressToEdging - progressX;
  253. }
  254. }else {
  255. if (progress <= 0.5) {
  256. progressX = fromCellFrame.origin.x + progressFromEdging - (toCellFrame.size.width-progressToEdging+progressFromEdging+_cellSpacing)*2*progress;
  257. width = CGRectGetMaxX(fromCellFrame) - progressFromEdging - progressX;
  258. }else {
  259. progressX = toCellFrame.origin.x + progressToEdging;
  260. width = (fromCellFrame.size.width-progressFromEdging+progressToEdging + _cellSpacing)*(1-progress)*2 + toCellFrame.size.width - 2*progressToEdging;
  261. }
  262. }
  263. }else if (_barStyle == TYPagerBarStyleProgressElasticView) {
  264. if (fromCellFrame.origin.x < toCellFrame.origin.x) {
  265. if (progress <= 0.5) {
  266. progressX = fromCellFrame.origin.x + progressFromEdging + (fromCellFrame.size.width-2*progressFromEdging)*progress;
  267. width = (toCellFrame.size.width-progressToEdging+progressFromEdging+_cellSpacing)*2*progress - (toCellFrame.size.width-2*progressToEdging)*progress + fromCellFrame.size.width-2*progressFromEdging-(fromCellFrame.size.width-2*progressFromEdging)*progress;
  268. }else {
  269. progressX = fromCellFrame.origin.x + progressFromEdging + (fromCellFrame.size.width-2*progressFromEdging)*0.5 + (fromCellFrame.size.width-progressFromEdging - (fromCellFrame.size.width-2*progressFromEdging)*0.5 +progressToEdging+_cellSpacing)*(progress-0.5)*2;
  270. width = CGRectGetMaxX(toCellFrame)-progressToEdging - progressX - (toCellFrame.size.width-2*progressToEdging)*(1-progress);
  271. }
  272. }else {
  273. if (progress <= 0.5) {
  274. progressX = fromCellFrame.origin.x + progressFromEdging - (toCellFrame.size.width-(toCellFrame.size.width-2*progressToEdging)/2-progressToEdging+progressFromEdging+_cellSpacing)*2*progress;
  275. width = CGRectGetMaxX(fromCellFrame) - (fromCellFrame.size.width-2*progressFromEdging)*progress - progressFromEdging - progressX;
  276. }else {
  277. progressX = toCellFrame.origin.x + progressToEdging+(toCellFrame.size.width-2*progressToEdging)*(1-progress);
  278. width = (fromCellFrame.size.width-progressFromEdging+progressToEdging-(fromCellFrame.size.width-2*progressFromEdging)/2 + _cellSpacing)*(1-progress)*2 + toCellFrame.size.width - 2*progressToEdging - (toCellFrame.size.width-2*progressToEdging)*(1-progress);
  279. }
  280. }
  281. }else {
  282. progressX = (toCellFrame.origin.x+progressToEdging-(fromCellFrame.origin.x+progressFromEdging))*progress+fromCellFrame.origin.x+progressFromEdging;
  283. width = (toCellFrame.size.width-2*progressToEdging)*progress + (fromCellFrame.size.width-2*progressFromEdging)*(1-progress);
  284. }
  285. progressView.frame = CGRectMake(progressX,progressY, width, _progressHeight);
  286. }
  287. - (void)layoutSubViews {
  288. if (CGRectIsEmpty(_pagerTabBar.frame)) {
  289. return;
  290. }
  291. if (_barStyle == TYPagerBarStyleCoverView) {
  292. self.progressHeight = CGRectGetHeight(_pagerTabBar.collectionView.frame) -self.progressVerEdging*2;
  293. self.progressRadius = _progressRadius > 0 ? _progressRadius : self.progressHeight/2;
  294. }
  295. [self setUnderLineFrameWithIndex:_pagerTabBar.curIndex animated:NO];
  296. }
  297. @end