口袋优选

WLScrollView.m 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. //
  2. // WLScrollView.m
  3. // WLScrollView
  4. //
  5. // Created by 张子豪 on 2017/11/16.
  6. // Copyright © 2017年 张子豪. All rights reserved.
  7. //
  8. #import "WLScrollView.h"
  9. @interface WLScrollView()<
  10. UIScrollViewDelegate,
  11. WLSubViewDelegate
  12. >
  13. {
  14. NSInteger _index; //标记数据源位置
  15. NSInteger _cellNum;//单元格 数量
  16. CGPoint _point; //重置位置
  17. CGRect _subFrame;
  18. CGFloat _subViewWith;
  19. }
  20. @property (nonatomic,strong)UIScrollView *scrollView;
  21. @property (nonatomic,strong)NSMutableArray *subViewAry; //容器数组
  22. @property (nonatomic,strong)NSMutableArray *reuseViewAry; //复用池view数组
  23. @property (nonatomic,strong)NSMutableArray *userViewAry; //在使用view数组
  24. @end
  25. @implementation WLScrollView
  26. - (instancetype)initWithFrame:(CGRect)frame{
  27. self = [super initWithFrame:frame];
  28. if (self) {
  29. [self createUI];
  30. }
  31. return self;
  32. }
  33. #pragma mark - 设置起始位置
  34. - (void)setIndex:(NSInteger)index{
  35. _index = index;
  36. }
  37. #pragma mark - 复用池查找
  38. - (WLSubView *)dequeueReuseCellWithIdentifier:(NSString *)identifier{
  39. for (WLSubView *sub in self.reuseViewAry) {
  40. if ([sub.identifier isEqualToString:identifier] && !sub.isUser) {
  41. dispatch_async(dispatch_get_main_queue(), ^{
  42. [self.reuseViewAry removeObject:sub];
  43. });
  44. return sub;
  45. }
  46. }
  47. return nil;
  48. }
  49. - (void)createUI{
  50. _index = 0;
  51. _scale = 0.7;
  52. _marginX = 10;
  53. _isAnimation = YES;
  54. _isEnableMargin = NO;
  55. _maxAnimationScale = 1.2;
  56. _minAnimationScale = 0.9;
  57. [self setDefault];
  58. [self setSubView];
  59. }
  60. - (void)setDefault{
  61. _subViewWith = self.frame.size.width * self.scale;
  62. _point = CGPointMake(_subViewWith*2, 0);
  63. _subFrame = CGRectMake(self.marginX ,0 ,_subViewWith - self.marginX * 2 ,self.frame.size.height);
  64. }
  65. - (void)setSubView{
  66. self.scrollView.frame = CGRectMake((self.frame.size.width-_subViewWith)/2, 0, _subViewWith, self.frame.size.height);
  67. self.scrollView.contentSize = CGSizeMake(_subViewWith*5, self.frame.size.height);
  68. [self.subViewAry removeAllObjects];
  69. [self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
  70. for (int i = 0; i<5; i++) {
  71. UIView *sub = [[UIView alloc]initWithFrame:CGRectMake(i*_subViewWith, 0, _subViewWith, self.frame.size.height)];
  72. [self.scrollView addSubview:sub];
  73. [self.subViewAry addObject:sub];
  74. }
  75. if (self.isAnimation) {
  76. for (UIView *sub in self.subViewAry) {
  77. sub.layer.transform = CATransform3DMakeScale(_minAnimationScale, _minAnimationScale, 1.0);
  78. }
  79. UIView *sub = (UIView *)[self.subViewAry objectAtIndex:2];
  80. sub.layer.transform = CATransform3DMakeScale(_maxAnimationScale, _maxAnimationScale, 1.0);
  81. }
  82. }
  83. - (void)starRender{
  84. [self setDefault];
  85. [self setSubView];
  86. [self upConfig];
  87. }
  88. #pragma mark - 刷新数据
  89. - (void)upConfig{
  90. [self checkOffset];//更新偏移
  91. [self checkCellnum];//更新Cellnum
  92. [self refreshCell];//更新显示数据
  93. [self currentIndex];//返回当前index
  94. }
  95. - (void)currentIndex{
  96. if (self.delegate && [self.delegate respondsToSelector:@selector(scrollView:didCurrentCellAtIndex:)]) {
  97. [self.delegate scrollView:self didCurrentCellAtIndex:_index];
  98. }
  99. }
  100. - (void)checkOffset{
  101. self.scrollView.contentOffset = _point;
  102. if (_isAnimation == NO) {return;}
  103. for (int i = 0 ; i<self.subViewAry.count; i++ ) {
  104. UIView *sub = [self.subViewAry objectAtIndex:i];
  105. if (i == 2) {
  106. sub.layer.transform = CATransform3DMakeScale(self.maxAnimationScale, self.maxAnimationScale, 1.0);
  107. }else{
  108. sub.layer.transform = CATransform3DMakeScale(self.minAnimationScale, self.minAnimationScale, 1.0);
  109. }
  110. }
  111. }
  112. - (void)checkCellnum{
  113. if (self.delegate && [self.delegate respondsToSelector:@selector(numOfContentViewScrollView:)]) {
  114. _cellNum = [self.delegate numOfContentViewScrollView:self];
  115. }else{
  116. NSAssert(NO, @"未实现 WLScrollViewDelegate 方法 numOfContentViewScrollView:");
  117. }
  118. }
  119. - (void)refreshCell{
  120. //获取数据源index数组
  121. NSArray *indexAry = [self checkIndexAry];
  122. //边缘隐藏
  123. [self checkHiden];
  124. for (int i = 0; i<5; i++) {
  125. //获取自定义view
  126. if (self.delegate && [self.delegate respondsToSelector:@selector(scrollView:subViewFrame:cellAtIndex:)]) {
  127. NSInteger index = [[indexAry objectAtIndex:i] integerValue];
  128. UIView *subView = [self.subViewAry objectAtIndex:i];
  129. //清除原有自定义view 在使用数组中移除 加入可复用数组
  130. for (WLSubView *sub in subView.subviews) {
  131. sub.isUser = NO;
  132. [self.userViewAry removeObject:sub];
  133. [self.reuseViewAry addObject:sub];
  134. [sub removeFromSuperview];
  135. }
  136. WLSubView *sub_view = [self.delegate scrollView:self subViewFrame:_subFrame cellAtIndex:index];
  137. sub_view.delegate = self;
  138. sub_view.isUser = YES;
  139. [self.userViewAry addObject:sub_view];
  140. [subView addSubview:sub_view];
  141. }else{
  142. NSAssert(NO, @"未实现 WLScrollViewDelegate 方法 scrollView:subViewFrame:cellAtIndex:");
  143. }
  144. }
  145. }
  146. #pragma mark - 边缘隐藏
  147. - (void)checkHiden{
  148. if (!_isEnableMargin) {return;}
  149. if (_index == 0) {
  150. UIView *subView = [self.subViewAry objectAtIndex:0];
  151. UIView *subView1 = [self.subViewAry objectAtIndex:1];
  152. subView.hidden = YES;
  153. subView1.hidden = YES;
  154. }else
  155. if (_index == 1) {
  156. UIView *subView = [self.subViewAry objectAtIndex:0];
  157. subView.hidden = YES;
  158. UIView *subView1 = [self.subViewAry objectAtIndex:1];
  159. subView1.hidden = NO;
  160. }else
  161. if (_index == 2) {
  162. UIView *subView = [self.subViewAry objectAtIndex:0];
  163. subView.hidden = NO;
  164. UIView *subView1 = [self.subViewAry objectAtIndex:1];
  165. subView1.hidden = NO;
  166. }
  167. if (_index == _cellNum-1) {
  168. UIView *subView = [self.subViewAry objectAtIndex:3];
  169. UIView *subView1 = [self.subViewAry objectAtIndex:4];
  170. subView.hidden = YES;
  171. subView1.hidden = YES;
  172. }else
  173. if (_index == _cellNum-2) {
  174. UIView *subView = [self.subViewAry objectAtIndex:4];
  175. subView.hidden = YES;
  176. UIView *subView1 = [self.subViewAry objectAtIndex:3];
  177. subView1.hidden = NO;
  178. }else
  179. if (_index == _cellNum-3) {
  180. UIView *subView = [self.subViewAry objectAtIndex:3];
  181. subView.hidden = NO;
  182. UIView *subView1 = [self.subViewAry objectAtIndex:4];
  183. subView1.hidden = NO;
  184. }
  185. }
  186. #pragma mark - 计算当前cell数据源index 存入数组
  187. - (NSArray *)checkIndexAry{
  188. //超出长度
  189. if (_index >= _cellNum) {
  190. _index = 0;
  191. }
  192. if (_index < 0) {
  193. _index = _cellNum + _index;
  194. }
  195. NSMutableArray *ary = [NSMutableArray new];
  196. NSInteger index_0 = _index - 2;
  197. NSInteger index_1 = _index - 1;
  198. NSInteger index_2 = _index;
  199. NSInteger index_3 = _index + 1;
  200. NSInteger index_4 = _index + 2;
  201. if (index_1 < 0) {
  202. index_1 = _cellNum + index_1;
  203. }
  204. if (index_0 < 0) {
  205. index_0 = _cellNum + index_0;
  206. }
  207. if (index_3 >= _cellNum) {
  208. index_3 = index_3 - _cellNum;
  209. }
  210. if (index_4 >= _cellNum) {
  211. index_4 = index_4 - _cellNum;
  212. }
  213. [ary addObject:[self stringOfint:index_0]];
  214. [ary addObject:[self stringOfint:index_1]];
  215. [ary addObject:[self stringOfint:index_2]];
  216. [ary addObject:[self stringOfint:index_3]];
  217. [ary addObject:[self stringOfint:index_4]];
  218. return ary;
  219. }
  220. #pragma mark - 动画函数
  221. - (void)animation{
  222. if (!_isAnimation) {
  223. return;
  224. }
  225. UIView *sub = (UIView*)[self.subViewAry objectAtIndex:2];
  226. UIView *subRight = (UIView*)[self.subViewAry objectAtIndex:3];
  227. UIView *subLift = (UIView*)[self.subViewAry objectAtIndex:1];
  228. CGFloat sum = self.scrollView.contentOffset.x+(_subViewWith)/2;
  229. CGFloat centerX = sub.center.x;
  230. CGFloat diff = sum - centerX;
  231. CGFloat shortX = _subViewWith;
  232. if (centerX <= sum && fabs(diff) <= shortX) {
  233. //向左滑动
  234. CGFloat scale = _maxAnimationScale-fabs(diff)/shortX* (_maxAnimationScale - _minAnimationScale);
  235. sub.layer.transform = CATransform3DMakeScale(scale, scale, 1.0);
  236. CGFloat scale1 = _minAnimationScale+fabs(diff)/shortX* (_maxAnimationScale - _minAnimationScale);
  237. subRight.layer.transform = CATransform3DMakeScale(scale1, scale1, 1.0);
  238. }
  239. if (centerX >= sum && fabs(diff) <= shortX) {
  240. //向右滑动
  241. CGFloat scale = _maxAnimationScale-fabs(diff)/shortX * (_maxAnimationScale - _minAnimationScale);
  242. sub.layer.transform = CATransform3DMakeScale(scale, scale, 1.0);
  243. CGFloat scale1 = _minAnimationScale+fabs(diff)/shortX * (_maxAnimationScale - _minAnimationScale);
  244. subLift.layer.transform = CATransform3DMakeScale(scale1, scale1, 1.0);
  245. }
  246. }
  247. #pragma mark - scrollDelegate
  248. - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
  249. CGFloat contentOffsetX = scrollView.contentOffset.x;
  250. if (_index == 0 && contentOffsetX < _point.x && _isEnableMargin) {
  251. scrollView.contentOffset = _point;
  252. return;
  253. }
  254. if (_index == _cellNum-1 && contentOffsetX > _point.x && _isEnableMargin) {
  255. scrollView.contentOffset = _point;
  256. return;
  257. }
  258. //判断左滑右滑
  259. if (contentOffsetX >= _subViewWith*3) {
  260. //offset向右滑动 +1
  261. _index += 1;
  262. //更新offset 刷新cell
  263. [self upConfig];
  264. }
  265. if (contentOffsetX <= _subViewWith){
  266. //向左滑动
  267. _index -= 1;
  268. //更新offset 刷新cell
  269. [self upConfig];
  270. }
  271. [self animation];
  272. }
  273. #pragma mark - WLSubViewDelegate
  274. - (void)didSelectedRespond{
  275. if (self.delegate && [self.delegate respondsToSelector:@selector(scrollView:didSelectedAtIndex:)]) {
  276. [self.delegate scrollView:self didSelectedAtIndex:_index];
  277. }else{
  278. NSAssert(NO, @"未实现 WLSubViewDelegate scrollView:didSelectedAtIndex:方法");
  279. }
  280. }
  281. - (NSString *)stringOfint:(NSInteger)num{
  282. return [NSString stringWithFormat:@"%zd",num];
  283. }
  284. #pragma mark - getter
  285. - (UIScrollView *)scrollView{
  286. if (!_scrollView) {
  287. CGFloat height = self.frame.size.height;
  288. _scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake((self.frame.size.width-_subViewWith)/2, 0, _subViewWith, height)];
  289. _scrollView.backgroundColor = [UIColor clearColor];
  290. _scrollView.pagingEnabled = YES;
  291. _scrollView.delegate = self;
  292. _scrollView.layer.masksToBounds = NO;
  293. _scrollView.contentSize = CGSizeMake(_subViewWith*5, height);
  294. _scrollView.showsHorizontalScrollIndicator = NO;
  295. _scrollView.showsVerticalScrollIndicator = NO;
  296. _scrollView.bounces = NO;
  297. _scrollView.decelerationRate = 0.1;
  298. [self addSubview:_scrollView];
  299. }
  300. return _scrollView;
  301. }
  302. - (NSMutableArray *)subViewAry{
  303. if (!_subViewAry) {
  304. _subViewAry = [NSMutableArray new];
  305. }
  306. return _subViewAry;
  307. }
  308. - (NSMutableArray *)reuseViewAry{
  309. if (!_reuseViewAry) {
  310. _reuseViewAry = [NSMutableArray new];
  311. }
  312. return _reuseViewAry;
  313. }
  314. - (NSMutableArray *)userViewAry{
  315. if (!_userViewAry) {
  316. _userViewAry = [NSMutableArray new];
  317. }
  318. return _userViewAry;
  319. }
  320. #pragma mark - setter
  321. - (void)setScrollViewType:(ScrollType)scrollViewType{
  322. if (scrollViewType == WLScrollViewRepeat) {
  323. self.scrollView.delegate = self;
  324. }
  325. _scrollViewType = scrollViewType;
  326. }
  327. - (CGRect)getSubFrame {
  328. return _subFrame;
  329. }
  330. @end