CGXVerticalMenuTitleView.m 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //
  2. // CGXVerticalMenuTitleView.m
  3. // CGXVerticalMenuView-OC
  4. //
  5. // Created by CGX on 2018/05/01.
  6. // Copyright © 2019 CGX. All rights reserved.
  7. //
  8. #import "CGXVerticalMenuTitleView.h"
  9. #import "CGXVerticalMenuTitleCell.h"
  10. #import "CGXVerticalMenuIndicatorBackgroundView.h"
  11. #import "CGXVerticalMenuIndicatorLineView.h"
  12. @interface CGXVerticalMenuTitleView()
  13. @property (nonatomic, assign) CGFloat isFirstClick;//是否第一次点击
  14. @end
  15. @implementation CGXVerticalMenuTitleView
  16. - (void)initializeData
  17. {
  18. [super initializeData];
  19. self.isFirstClick = YES;
  20. self.timeDuration = 0;
  21. self.clickedPosition = CGXCategoryListCellClickedPosition_Left;
  22. }
  23. - (void)initializeViews
  24. {
  25. [super initializeViews];
  26. CGXVerticalMenuIndicatorBackgroundView *backgroundView = [[CGXVerticalMenuIndicatorBackgroundView alloc] init];
  27. backgroundView.backgroundViewColor = [UIColor orangeColor];
  28. backgroundView.backgroundViewCornerRadius = 0;
  29. CGXVerticalMenuIndicatorLineView *lineView = [[CGXVerticalMenuIndicatorLineView alloc] init];
  30. lineView.backgroundColor = [UIColor redColor];
  31. lineView.positionType = CGXVerticalMenuIndicatorLinePosition_Left;
  32. self.indicators = @[lineView,backgroundView];
  33. }
  34. - (Class)preferredCellClass
  35. {
  36. return CGXVerticalMenuTitleCell.class;
  37. }
  38. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
  39. {
  40. [self selectCellAtIndex:indexPath.section selectedType:CGXCategoryListCellSelectedTypeClick];
  41. }
  42. - (void)updateMenuWithDataArray:(NSMutableArray<CGXVerticalMenuBaseModel *> *)dataArray
  43. {
  44. [super updateMenuWithDataArray:dataArray];
  45. for (UIView<CGXCategoryListIndicatorProtocol> *indicator in self.indicators) {
  46. if (self.dataArray.count <= 0) {
  47. indicator.hidden = YES;
  48. }else {
  49. indicator.hidden = NO;
  50. CGXVerticalMenuTitleModel *model = (CGXVerticalMenuTitleModel *)self.dataArray[self.selectedIndex];
  51. NSInteger lastSelectedIndex = self.selectedIndex;
  52. CGRect clickedCellFrame = CGRectMake(0, self.selectedIndex *model.rowHeight , self.frame.size.width, model.rowHeight);
  53. CGXVerticalMenuIndicatorParamsModel *indicatorParamsModel = [[CGXVerticalMenuIndicatorParamsModel alloc] init];
  54. indicatorParamsModel.selectedIndex = self.selectedIndex;
  55. indicatorParamsModel.lastSelectedIndex = lastSelectedIndex;
  56. indicatorParamsModel.selectedCellFrame = clickedCellFrame;
  57. indicatorParamsModel.isFirstClick = self.isFirstClick;
  58. indicatorParamsModel.timeDuration = self.timeDuration;
  59. [indicator listIndicatorRefreshState:indicatorParamsModel];
  60. if ([indicator isKindOfClass:[CGXVerticalMenuIndicatorBackgroundView class]]) {
  61. CGRect maskFrame = indicator.frame;
  62. maskFrame.origin.x = maskFrame.origin.x - clickedCellFrame.origin.x;
  63. indicatorParamsModel.backgroundViewMaskFrame = clickedCellFrame;
  64. }
  65. }
  66. }
  67. [self selectItemAtIndex:self.selectedIndex];
  68. }
  69. - (void)refreshCellModel:(CGXVerticalMenuBaseModel *)cellModel index:(NSInteger)index
  70. {
  71. [super refreshCellModel:cellModel index:index];
  72. // CGXVerticalMenuTitleModel *model = (CGXVerticalMenuTitleModel *)cellModel;
  73. }
  74. - (void)refreshSelectedCellModel:(CGXVerticalMenuBaseModel *)selectedCellModel unselectedCellModel:(CGXVerticalMenuBaseModel *)unselectedCellModel
  75. {
  76. [super refreshSelectedCellModel:selectedCellModel unselectedCellModel:unselectedCellModel];
  77. }
  78. /**
  79. 选中目标index的item
  80. @param index 目标index
  81. */
  82. - (void)selectItemAtIndex:(NSInteger)index
  83. {
  84. [self selectCellAtIndex:index selectedType:CGXCategoryListCellSelectedTypeClick];
  85. }
  86. /**
  87. 滚动目标index的item
  88. @param index 目标index
  89. */
  90. - (void)scrollerItemAtIndex:(NSInteger)index
  91. {
  92. [self selectCellAtIndex:index selectedType:CGXCategoryListCellSelectedTypeScroll];
  93. }
  94. - (void)selectCellAtIndex:(NSInteger)index selectedType:(CGXCategoryListCellSelectedType)selectedType
  95. {
  96. if (self.dataArray.count==0) {
  97. return;
  98. }
  99. if (index>self.dataArray.count-1) {
  100. return;
  101. }
  102. if (self.selectedIndex == index) {
  103. if (self.isFirstClick) {
  104. self.isFirstClick = !self.isFirstClick;
  105. [self updateIndicatorAtIndex:index selectedType:selectedType]; //更新指示器
  106. } else{
  107. CGXVerticalMenuTitleModel *newModel = (CGXVerticalMenuTitleModel *)self.dataArray[index];
  108. if (newModel.isMoreClick) {
  109. [self updateCellAtIndex:index selectedType:selectedType];
  110. }
  111. }
  112. return;
  113. } else{
  114. [self updateIndicatorAtIndex:index selectedType:selectedType]; //更新指示器
  115. }
  116. //通知子类刷新当前选中的和将要选中的cellModel
  117. CGXVerticalMenuTitleModel *oldModel = (CGXVerticalMenuTitleModel *)self.dataArray[self.selectedIndex];
  118. CGXVerticalMenuTitleModel *newModel = (CGXVerticalMenuTitleModel *)self.dataArray[index];
  119. [self refreshSelectedCellModel:newModel unselectedCellModel:oldModel];
  120. //刷新当前选中的和将要选中的cell
  121. CGXVerticalMenuTitleCell *lastCell = (CGXVerticalMenuTitleCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:self.selectedIndex]];
  122. [lastCell reloadData:oldModel];
  123. CGXVerticalMenuTitleCell *selectedCell = (CGXVerticalMenuTitleCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:index]];
  124. [selectedCell reloadData:newModel];
  125. if (self.selectedIndex == index) {
  126. if (self.isFirstClick) {
  127. [self updateCellAtIndex:index selectedType:selectedType];
  128. [self updateDelegateAtIndex:index selectedType:selectedType];
  129. self.isFirstClick = NO;
  130. } else{
  131. if (newModel.isMoreClick) {
  132. [self updateCellAtIndex:index selectedType:selectedType];
  133. [self updateDelegateAtIndex:index selectedType:selectedType];
  134. }
  135. }
  136. } else{
  137. [self updateCellAtIndex:index selectedType:selectedType];
  138. [self updateDelegateAtIndex:index selectedType:selectedType];
  139. }
  140. self.isFirstClick = NO;
  141. self.selectedIndex = index;
  142. }
  143. #pragma mark - 更新指示器
  144. - (void)updateIndicatorAtIndex:(NSInteger)index selectedType:(CGXCategoryListCellSelectedType)selectedType
  145. {
  146. CGXVerticalMenuTitleModel *model = (CGXVerticalMenuTitleModel *)self.dataArray[index];
  147. NSInteger lastSelectedIndex = index;
  148. CGRect clickedCellFrame = CGRectMake(0, index *model.rowHeight , self.frame.size.width, model.rowHeight);
  149. for (UIView<CGXCategoryListIndicatorProtocol> *indicator in self.indicators) {
  150. CGXVerticalMenuIndicatorParamsModel *indicatorParamsModel = [[CGXVerticalMenuIndicatorParamsModel alloc] init];
  151. indicatorParamsModel.lastSelectedIndex = lastSelectedIndex;
  152. indicatorParamsModel.selectedIndex = index;
  153. indicatorParamsModel.selectedCellFrame = clickedCellFrame;
  154. indicatorParamsModel.selectedType = selectedType;
  155. indicatorParamsModel.isFirstClick = self.isFirstClick;
  156. indicatorParamsModel.timeDuration = self.timeDuration;
  157. if ([indicator isKindOfClass:[CGXVerticalMenuIndicatorBackgroundView class]]) {
  158. CGRect maskFrame = indicator.frame;
  159. maskFrame.origin.x = maskFrame.origin.x - clickedCellFrame.origin.x;
  160. indicatorParamsModel.backgroundViewMaskFrame = clickedCellFrame;
  161. }
  162. [indicator listIndicatorSelectedCell:indicatorParamsModel];
  163. }
  164. }
  165. #pragma mark - 更新cell
  166. - (void)updateCellAtIndex:(NSInteger)index selectedType:(CGXCategoryListCellSelectedType)selectedType
  167. {
  168. [CATransaction setDisableActions:YES];
  169. dispatch_async(dispatch_get_main_queue(), ^{
  170. [self.collectionView reloadData];
  171. });
  172. [CATransaction commit];
  173. [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:index] atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:YES];
  174. }
  175. #pragma mark - 更新代理
  176. - (void)updateDelegateAtIndex:(NSInteger)index selectedType:(CGXCategoryListCellSelectedType)selectedType
  177. {
  178. //目标index和当前选中的index相等,就不需要处理后续的选中更新逻辑,只需要回调代理方法即可。
  179. if (selectedType == CGXCategoryListCellSelectedTypeClick) {
  180. // 点击选中
  181. if (self.delegate && [self.delegate respondsToSelector:@selector(verticalMenuTitleView:didClickSelectedItemAtIndex:)]) {
  182. [self.delegate verticalMenuTitleView:self didClickSelectedItemAtIndex:index];
  183. }
  184. }else if (selectedType == CGXCategoryListCellSelectedTypeScroll) {
  185. if (self.delegate && [self.delegate respondsToSelector:@selector(verticalMenuTitleView:didScrollerSelectedItemAtIndex:)]) {
  186. [self.delegate verticalMenuTitleView:self didScrollerSelectedItemAtIndex:index];
  187. }
  188. }
  189. if (self.delegate && [self.delegate respondsToSelector:@selector(verticalMenuTitleView:didSelectedItemAtIndex:)]) {
  190. [self.delegate verticalMenuTitleView:self didSelectedItemAtIndex:index];
  191. }
  192. }
  193. /*
  194. // Only override drawRect: if you perform custom drawing.
  195. // An empty implementation adversely affects performance during animation.
  196. - (void)drawRect:(CGRect)rect {
  197. // Drawing code
  198. }
  199. */
  200. @end