NIMPageView.m 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. //
  2. // NIMInputPageView.m
  3. // NIMKit
  4. //
  5. // Created by chris.
  6. // Copyright (c) 2015年 NetEase. All rights reserved.
  7. //
  8. #import "NIMPageView.h"
  9. @interface NIMPageView ()
  10. {
  11. NSInteger _currentPage;
  12. NSInteger _currentPageForRotation;
  13. }
  14. @property (nonatomic,strong) NSMutableArray *pages;
  15. - (void)setupControls;
  16. //重新载入的流程
  17. - (void)calculatePageNumbers;
  18. - (void)reloadPage;
  19. - (void)raisePageIndexChangedDelegate;
  20. @end
  21. @implementation NIMPageView
  22. - (id)initWithFrame:(CGRect)frame
  23. {
  24. self = [super initWithFrame:frame];
  25. if (self)
  26. {
  27. [self setupControls];
  28. }
  29. return self;
  30. }
  31. - (id)initWithCoder:(NSCoder *)aDecoder
  32. {
  33. if (self = [super initWithCoder:aDecoder])
  34. {
  35. [self setupControls];
  36. }
  37. return self;
  38. }
  39. - (void)setFrame:(CGRect)frame{
  40. CGFloat originalWidth = self.frame.size.width;
  41. [super setFrame:frame];
  42. if (originalWidth != frame.size.width) {
  43. [self reloadData];
  44. }
  45. }
  46. - (void)dealloc
  47. {
  48. _scrollView.delegate = nil;
  49. }
  50. - (void)layoutSubviews
  51. {
  52. [super layoutSubviews];
  53. [_scrollView setFrame:self.bounds];
  54. CGSize size = self.bounds.size;
  55. [self.scrollView setContentSize:CGSizeMake(size.width * [self.pages count], size.height)];
  56. for (NSInteger i = 0; i < [self.pages count]; i++)
  57. {
  58. id obj = [self.pages objectAtIndex:i];
  59. if ([obj isKindOfClass:[UIView class]])
  60. {
  61. [(UIView *)obj setFrame:CGRectMake(size.width * i, 0, size.width, size.height)];
  62. }
  63. }
  64. //CGSize size = self.bounds.size;
  65. BOOL animation = NO;
  66. if (self.pageViewDelegate && [self.pageViewDelegate respondsToSelector:@selector(needScrollAnimation)])
  67. {
  68. animation = [self.pageViewDelegate needScrollAnimation];
  69. }
  70. [self.scrollView scrollRectToVisible:CGRectMake(_currentPage * size.width, 0, size.width, size.height)
  71. animated:animation];
  72. }
  73. - (void)setupControls
  74. {
  75. if (_scrollView == nil)
  76. {
  77. _scrollView = [[UIScrollView alloc]initWithFrame:self.bounds];
  78. _scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  79. [self addSubview:_scrollView];
  80. _scrollView.pagingEnabled = YES;
  81. _scrollView.showsVerticalScrollIndicator = NO;
  82. _scrollView.showsHorizontalScrollIndicator = NO;
  83. _scrollView.delegate = self;
  84. _scrollView.scrollsToTop = NO;
  85. }
  86. }
  87. #pragma mark - 对外接口
  88. - (void)scrollToPage: (NSInteger)page
  89. {
  90. if (_currentPage != page || page == 0)
  91. {
  92. _currentPage = page;
  93. [self reloadData];
  94. }
  95. }
  96. - (void)reloadData
  97. {
  98. [self calculatePageNumbers];
  99. [self reloadPage];
  100. }
  101. - (UIView *)viewAtIndex: (NSInteger)index
  102. {
  103. UIView *view = nil;
  104. if (index >= 0 && index < [_pages count])
  105. {
  106. id obj = [_pages objectAtIndex:index];
  107. if ([obj isKindOfClass:[UIView class]])
  108. {
  109. view = obj;
  110. }
  111. }
  112. return view;
  113. }
  114. - (NSInteger)currentPage
  115. {
  116. return _currentPage;
  117. }
  118. - (NSInteger)pageInBound:(NSInteger)value min:(NSInteger)min max:(NSInteger)max{
  119. if (max < min) {
  120. max = min;
  121. }
  122. NSInteger bounded = value;
  123. if (bounded > max) {
  124. bounded = max;
  125. }
  126. if (bounded < min) {
  127. bounded = min;
  128. }
  129. return bounded;
  130. }
  131. #pragma mark - Page载入和销毁
  132. - (void)loadPagesForCurrentPage:(NSInteger)currentPage
  133. {
  134. NSUInteger count = [_pages count];
  135. if (count == 0)
  136. {
  137. return;
  138. }
  139. NSInteger first = [self pageInBound:currentPage - 1 min:0 max:count - 1];
  140. NSInteger last = [self pageInBound:currentPage + 1 min:0 max:count - 1];
  141. NSRange range = NSMakeRange(first, last - first + 1);
  142. for (NSUInteger index = 0; index < count; index++)
  143. {
  144. if (NSLocationInRange(index, range))
  145. {
  146. id obj = [_pages objectAtIndex:index];
  147. if (![obj isKindOfClass:[UIView class]])
  148. {
  149. if (_dataSource && [_dataSource respondsToSelector:@selector(pageView:viewInPage:)])
  150. {
  151. UIView *view = [_dataSource pageView:self viewInPage:index];
  152. [_pages replaceObjectAtIndex:index withObject:view];
  153. [self.scrollView addSubview:view];
  154. CGSize size = self.bounds.size;
  155. [view setFrame:CGRectMake(size.width * index, 0, size.width, size.height)];
  156. }
  157. else
  158. {
  159. assert(0);
  160. }
  161. }
  162. }
  163. else
  164. {
  165. id obj = [_pages objectAtIndex:index];
  166. if ([obj isKindOfClass:[UIView class]])
  167. {
  168. [obj removeFromSuperview];
  169. [_pages replaceObjectAtIndex:index withObject:[NSNull null]];
  170. }
  171. }
  172. }
  173. }
  174. - (void)calculatePageNumbers
  175. {
  176. NSInteger numberOfPages = 0;
  177. for (id obj in _pages)
  178. {
  179. if ([obj isKindOfClass:[UIView class]])
  180. {
  181. [(UIView *)obj removeFromSuperview];
  182. }
  183. }
  184. if(_dataSource && [_dataSource respondsToSelector:@selector(numberOfPages:)])
  185. {
  186. numberOfPages = [_dataSource numberOfPages:self];
  187. }
  188. self.pages = [NSMutableArray arrayWithCapacity:numberOfPages];
  189. for (NSInteger i = 0; i < numberOfPages; i ++)
  190. {
  191. [_pages addObject:[NSNull null]];
  192. }
  193. //注意,这里设置delegate是因为计算contentsize的时候会引起scrollViewDidScroll执行,修改currentpage的值,这样在贴图(举个例子)前面的分类页数比后面的分类页数多,前面的分类滚动到最后面一页后,再显示后面的分类,会显示不正确
  194. self.scrollView.delegate = nil;
  195. CGSize size = self.bounds.size;
  196. [self.scrollView setContentSize:CGSizeMake(size.width * numberOfPages, size.height)];
  197. self.scrollView.delegate = self;
  198. }
  199. - (void)reloadPage
  200. {
  201. //reload的时候尽量记住上次的位置
  202. if (_currentPage >= [_pages count])
  203. {
  204. _currentPage = [_pages count] - 1;
  205. }
  206. if (_currentPage < 0)
  207. {
  208. _currentPage = 0;
  209. }
  210. [self loadPagesForCurrentPage:_currentPage];
  211. [self raisePageIndexChangedDelegate];
  212. [self setNeedsLayout];
  213. }
  214. #pragma mark - ScrollView Delegate
  215. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  216. {
  217. CGFloat width = scrollView.bounds.size.width;
  218. CGFloat offsetX = scrollView.contentOffset.x;
  219. NSInteger page = (NSInteger)(fabs(offsetX / width));
  220. if (page >= 0 && page < [_pages count])
  221. {
  222. if (_currentPage == page) {
  223. return;
  224. }
  225. _currentPage = page;
  226. [self loadPagesForCurrentPage:_currentPage];
  227. }
  228. if (_pageViewDelegate && [_pageViewDelegate respondsToSelector:@selector(pageViewDidScroll:)])
  229. {
  230. [_pageViewDelegate pageViewDidScroll:self];
  231. }
  232. }
  233. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
  234. {
  235. [self raisePageIndexChangedDelegate];
  236. }
  237. #pragma mark - 辅助方法
  238. - (void)raisePageIndexChangedDelegate
  239. {
  240. if (_pageViewDelegate && [_pageViewDelegate respondsToSelector:@selector(pageViewScrollEnd:currentIndex:totolPages:)])
  241. {
  242. [_pageViewDelegate pageViewScrollEnd:self
  243. currentIndex:_currentPage
  244. totolPages:[_pages count]];
  245. }
  246. }
  247. - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
  248. duration:(NSTimeInterval)duration
  249. {
  250. _scrollView.delegate = nil;
  251. _currentPageForRotation = _currentPage;
  252. }
  253. - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
  254. duration:(NSTimeInterval)duration
  255. {
  256. CGSize size = self.bounds.size;
  257. _scrollView.contentSize = CGSizeMake(size.width * [_pages count], size.height);
  258. for (NSUInteger i = 0; i < [_pages count]; i++)
  259. {
  260. id obj = [_pages objectAtIndex:i];
  261. if ([obj isKindOfClass:[UIView class]])
  262. {
  263. [(UIView *)obj setFrame:CGRectMake(size.width * i, 0, size.width, size.height)];
  264. /*
  265. //这里有点ugly,先这样吧...
  266. if ([obj respondsToSelector:@selector(reset)])
  267. {
  268. [obj performSelector:@selector(reset)];
  269. }*/
  270. }
  271. }
  272. _scrollView.contentOffset = CGPointMake(_currentPageForRotation * self.bounds.size.width, 0);
  273. _scrollView.delegate = self;
  274. }
  275. @end