JXCategoryBaseView.h 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. //
  2. // JXCategoryView.h
  3. // UI系列测试
  4. //
  5. // Created by jiaxin on 2018/3/15.
  6. // Copyright © 2018年 jiaxin. All rights reserved.
  7. //
  8. #import <UIKit/UIKit.h>
  9. #import "JXCategoryBaseCell.h"
  10. #import "JXCategoryBaseCellModel.h"
  11. #import "JXCategoryCollectionView.h"
  12. #import "JXCategoryViewDefines.h"
  13. @class JXCategoryBaseView;
  14. @protocol JXCategoryViewListContainer <NSObject>
  15. - (void)setDefaultSelectedIndex:(NSInteger)index;
  16. - (UIScrollView *)contentScrollView;
  17. - (void)reloadData;
  18. - (void)scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio selectedIndex:(NSInteger)selectedIndex;
  19. - (void)didClickSelectedItemAtIndex:(NSInteger)index;
  20. @end
  21. @protocol JXCategoryViewDelegate <NSObject>
  22. @optional
  23. //为什么会把选中代理分为三个,因为有时候只关心点击选中的,有时候只关心滚动选中的,有时候只关心选中。所以具体情况,使用对应方法。
  24. /**
  25. 点击选中或者滚动选中都会调用该方法。适用于只关心选中事件,不关心具体是点击还是滚动选中的。
  26. @param categoryView categoryView对象
  27. @param index 选中的index
  28. */
  29. - (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index;
  30. /**
  31. 点击选中的情况才会调用该方法
  32. @param categoryView categoryView对象
  33. @param index 选中的index
  34. */
  35. - (void)categoryView:(JXCategoryBaseView *)categoryView didClickSelectedItemAtIndex:(NSInteger)index;
  36. /**
  37. 滚动选中的情况才会调用该方法
  38. @param categoryView categoryView对象
  39. @param index 选中的index
  40. */
  41. - (void)categoryView:(JXCategoryBaseView *)categoryView didScrollSelectedItemAtIndex:(NSInteger)index;
  42. /**
  43. 控制能否点击Item
  44. @param categoryView categoryView对象
  45. @param index 准备点击的index
  46. @return 能否点击
  47. */
  48. - (BOOL)categoryView:(JXCategoryBaseView *)categoryView canClickItemAtIndex:(NSInteger)index;
  49. /**
  50. 正在滚动中的回调
  51. @param categoryView categoryView对象
  52. @param leftIndex 正在滚动中,相对位置处于左边的index
  53. @param rightIndex 正在滚动中,相对位置处于右边的index
  54. @param ratio 从左往右计算的百分比
  55. */
  56. - (void)categoryView:(JXCategoryBaseView *)categoryView scrollingFromLeftIndex:(NSInteger)leftIndex toRightIndex:(NSInteger)rightIndex ratio:(CGFloat)ratio;
  57. @end
  58. @interface JXCategoryBaseView : UIView
  59. @property (nonatomic, strong, readonly) JXCategoryCollectionView *collectionView;
  60. @property (nonatomic, strong) NSArray <JXCategoryBaseCellModel *> *dataSource;
  61. @property (nonatomic, weak) id<JXCategoryViewDelegate> delegate;
  62. /**
  63. 高封装度的列表容器,使用该类可以让列表拥有完成的生命周期、自动同步defaultSelectedIndex、自动调用reloadData。
  64. */
  65. @property (nonatomic, weak) id<JXCategoryViewListContainer> listContainer;
  66. /**
  67. 推荐使用封装度更高的listContainer属性。如果使用contentScrollView请参考`LoadDataListCustomViewController`使用示例。
  68. */
  69. @property (nonatomic, strong) UIScrollView *contentScrollView;
  70. @property (nonatomic, assign) NSInteger defaultSelectedIndex; //修改初始化的时候默认选择的index
  71. @property (nonatomic, assign, readonly) NSInteger selectedIndex;
  72. @property (nonatomic, assign, getter=isContentScrollViewClickTransitionAnimationEnabled) BOOL contentScrollViewClickTransitionAnimationEnabled; //点击cell进行contentScrollView切换时是否需要动画。默认为YES
  73. @property (nonatomic, assign) CGFloat contentEdgeInsetLeft; //整体内容的左边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing)
  74. @property (nonatomic, assign) CGFloat contentEdgeInsetRight; //整体内容的右边距,默认JXCategoryViewAutomaticDimension(等于cellSpacing)
  75. @property (nonatomic, assign) CGFloat cellWidth; //默认JXCategoryViewAutomaticDimension
  76. @property (nonatomic, assign) CGFloat cellWidthIncrement; //cell宽度补偿。默认:0
  77. @property (nonatomic, assign) CGFloat cellSpacing; //cell之间的间距,默认20
  78. @property (nonatomic, assign, getter=isAverageCellSpacingEnabled) BOOL averageCellSpacingEnabled; //当collectionView.contentSize.width小于JXCategoryBaseView的宽度,是否将cellSpacing均分。默认为YES。
  79. //cell宽度是否缩放
  80. @property (nonatomic, assign, getter=isCellWidthZoomEnabled) BOOL cellWidthZoomEnabled; //默认为NO
  81. @property (nonatomic, assign, getter=isCellWidthZoomScrollGradientEnabled) BOOL cellWidthZoomScrollGradientEnabled; //手势滚动过程中,是否需要更新cell的宽度。默认为YES
  82. @property (nonatomic, assign) CGFloat cellWidthZoomScale; //默认1.2,cellWidthZoomEnabled为YES才生效
  83. @property (nonatomic, assign, getter=isSelectedAnimationEnabled) BOOL selectedAnimationEnabled; //是否开启选中动画。默认为NO。自定义的cell选中动画需要自己实现。
  84. @property (nonatomic, assign) NSTimeInterval selectedAnimationDuration; //cell选中动画的时间。默认0.25
  85. /**
  86. 选中目标index的item
  87. 如果要同时触发列表容器对应index的列表加载,请再调用`[self.listContainerView didClickSelectedItemAtIndex:index];`方法
  88. @param index 目标index
  89. */
  90. - (void)selectItemAtIndex:(NSInteger)index;
  91. /**
  92. 初始化的时候无需调用。比如页面初始化之后,根据网络接口异步回调回来数据,重新配置categoryView,需要调用该方法进行刷新。
  93. */
  94. - (void)reloadData;
  95. /**
  96. 重新配置categoryView但是不需要reload listContainer。特殊情况是该方法。
  97. */
  98. - (void)reloadDataWithoutListContainer;
  99. /**
  100. 刷新指定的index的cell
  101. 内部会触发`- (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index`方法进行cellModel刷新
  102. @param index 指定cell的index
  103. */
  104. - (void)reloadCellAtIndex:(NSInteger)index;
  105. @end
  106. @interface JXCategoryBaseView (UISubclassingBaseHooks)
  107. /**
  108. 获取目标cell当前的frame,反应当前真实的frame受到cellWidthSelectedZoomScale的影响。
  109. */
  110. - (CGRect)getTargetCellFrame:(NSInteger)targetIndex;
  111. /**
  112. 获取目标cell的选中时的frame,其他cell的状态都当做普通状态处理。
  113. */
  114. - (CGRect)getTargetSelectedCellFrame:(NSInteger)targetIndex selectedType:(JXCategoryCellSelectedType)selectedType;
  115. - (void)initializeData NS_REQUIRES_SUPER;
  116. - (void)initializeViews NS_REQUIRES_SUPER;
  117. /**
  118. reloadData方法调用,重新生成数据源赋值到self.dataSource
  119. */
  120. - (void)refreshDataSource;
  121. /**
  122. reloadData方法调用,根据数据源重新刷新状态;
  123. */
  124. - (void)refreshState NS_REQUIRES_SUPER;
  125. /**
  126. 选中某个item时,刷新将要选中与取消选中的cellModel
  127. @param selectedCellModel 将要选中的cellModel
  128. @param unselectedCellModel 取消选中的cellModel
  129. */
  130. - (void)refreshSelectedCellModel:(JXCategoryBaseCellModel *)selectedCellModel unselectedCellModel:(JXCategoryBaseCellModel *)unselectedCellModel NS_REQUIRES_SUPER;
  131. /**
  132. 关联的contentScrollView的contentOffset发生了改变
  133. @param contentOffset 偏移量
  134. */
  135. - (void)contentOffsetOfContentScrollViewDidChanged:(CGPoint)contentOffset NS_REQUIRES_SUPER;
  136. /**
  137. 选中某一个item的时候调用,该方法用于子类重载。
  138. 如果外部要选中某个index,请使用`- (void)selectItemAtIndex:(NSUInteger)index;`
  139. @param index 选中的index
  140. @param selectedType JXCategoryCellSelectedType
  141. @return 返回值为NO,表示触发内部某些判断(点击了同一个cell),子类无需后续操作。
  142. */
  143. - (BOOL)selectCellAtIndex:(NSInteger)index selectedType:(JXCategoryCellSelectedType)selectedType NS_REQUIRES_SUPER;
  144. /**
  145. reloadData时,返回每个cell的宽度
  146. @param index 目标index
  147. @return cellWidth
  148. */
  149. - (CGFloat)preferredCellWidthAtIndex:(NSInteger)index;
  150. /**
  151. 返回自定义cell的class
  152. @return cell class
  153. */
  154. - (Class)preferredCellClass;
  155. /**
  156. refreshState时调用,重置cellModel的状态
  157. @param cellModel 待重置的cellModel
  158. @param index cellModel在数组中的index
  159. */
  160. - (void)refreshCellModel:(JXCategoryBaseCellModel *)cellModel index:(NSInteger)index NS_REQUIRES_SUPER;
  161. @end