DKAnimationScrollView.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. //
  2. // ZLAnimationScrollView.m
  3. // ZLAssetsPickerDemo
  4. //
  5. //
  6. #import "DKAnimationScrollView.h"
  7. #import "UIView+Extension.h"
  8. #import "DKPhotoPickerCommon.h"
  9. static UIView *_parsentView;
  10. static NSArray *_photos;
  11. static NSMutableDictionary *_attachParams = nil;
  12. static NSArray *_subViews = nil;
  13. @implementation DKAnimationScrollView
  14. + (NSDictionary *)updateOptions:(NSDictionary *)updateOptions statusStart:(BOOL)start{
  15. if (!_attachParams) {
  16. _attachParams = [NSMutableDictionary dictionary];
  17. }
  18. NSMutableDictionary *ops = [NSMutableDictionary dictionaryWithDictionary:updateOptions];
  19. if (!start) {
  20. if ([[self currentIndexPath] item] >= KPhotoShowMaxCount) {
  21. ops[UIViewAnimationAnimationStatusType] = @(UIViewAnimationAnimationStatusFade);
  22. }
  23. }
  24. [ops addEntriesFromDictionary:_attachParams];
  25. return ops;
  26. }
  27. + (instancetype)animationViewWithOptions:(NSDictionary *)options animations:(void (^)())animations completion:(void (^)(DKAnimationBaseView *))completion{
  28. options = [self updateOptions:options statusStart:YES];
  29. UIView *toView = options[UIViewAnimationToView];
  30. if ([_attachParams[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusZoom && (![self getCollectionViewWithView:toView])) {
  31. toView.hidden = YES;
  32. }
  33. _photos = options[UIViewAnimationImages];
  34. _parsentView = toView.superview;
  35. return [super animationViewWithOptions:options animations:animations completion:completion];
  36. }
  37. + (void)restoreWithOptions:(NSDictionary *)options animation:(void (^)())completion{
  38. options = [self updateOptions:options statusStart:NO];
  39. NSMutableDictionary *ops = [NSMutableDictionary dictionaryWithDictionary:options];
  40. UIView *toView = options[UIViewAnimationToView];
  41. UITableView *tableView = (UITableView *)[self getTableViewWithView:toView];
  42. UICollectionView *collectionView = (UICollectionView *)[self getCollectionViewWithView:toView];
  43. UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)collectionView.collectionViewLayout;
  44. UICollectionViewScrollDirection direction = flowLayout.scrollDirection;
  45. if ([options[UIViewAnimationAnimationStatusType] longLongValue] == UIViewAnimationAnimationStatusFade) {
  46. toView.hidden = NO;
  47. }
  48. __block NSArray *subViews = nil;
  49. // 如果是TableView子控件的话
  50. if (tableView || collectionView) {
  51. if (tableView) {
  52. if ([[toView.superview subviews] count] == [options[UIViewAnimationImages] count]){
  53. subViews = [toView.superview subviews];
  54. }else{
  55. subViews = [tableView visibleCells];
  56. }
  57. }else{
  58. // note:collectionView visibleCells 里面的元素并不是按frame来排序的
  59. // 进行frame来排序
  60. NSMutableArray *cells = [[NSMutableArray alloc] init];
  61. NSMutableArray *frames = [[NSMutableArray alloc] init];
  62. if (collectionView.visibleCells.count == 0) {
  63. ops[UIViewAnimationAnimationStatusType] = @(UIViewAnimationAnimationStatusFade);
  64. }
  65. NSUInteger index = [collectionView.dataSource collectionView:collectionView numberOfItemsInSection:[options[UIViewAnimationTypeViewWithIndexPath] section]];
  66. for (NSInteger i = 0; i < index; i++) {
  67. UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForItem:i inSection:[options[UIViewAnimationTypeViewWithIndexPath] section]]];
  68. if (cell) {
  69. [cells addObject:cell];
  70. }
  71. }
  72. // subViews = [collectionView.dataSource collectionView:<#(UICollectionView *)#> cellForItemAtIndexPath:<#(NSIndexPath *)#>];
  73. // if ([[collectionView visibleCells] count]) {
  74. // subViews = [collectionView visibleCells];
  75. // }else{
  76. // subViews = [[self getCollectionViewWithCell:_parsentView] subviews];
  77. // }
  78. for (UICollectionViewCell *cell in cells) {
  79. if (![cell isKindOfClass:[UICollectionViewCell class]]) {
  80. continue;
  81. }
  82. if ([options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusZoom) {
  83. cell.hidden = NO;
  84. }
  85. [frames addObject:[NSValue valueWithCGRect:cell.frame]];
  86. }
  87. NSMutableSet *set = [NSMutableSet setWithArray:frames];
  88. for (NSValue *val in [set allObjects]) {
  89. for (UICollectionViewCell *cell in subViews) {
  90. if (CGRectEqualToRect(cell.frame, [val CGRectValue])) {
  91. [cells addObject:cell];
  92. break;
  93. }
  94. }
  95. }
  96. cells = [NSMutableArray arrayWithArray:[cells sortedArrayUsingComparator:^NSComparisonResult(UICollectionViewCell *cell1,UICollectionViewCell *cell2) {
  97. NSValue *obj1 = [NSValue valueWithCGRect:[cell1.superview convertRect:cell1.frame toView:options[UIViewAnimationFromView]]];
  98. NSValue *obj2 = [NSValue valueWithCGRect:[cell2.superview convertRect:cell2.frame toView:options[UIViewAnimationFromView]]];
  99. CGRect rc1 = [obj1 CGRectValue];
  100. CGRect rc2 = [obj2 CGRectValue];
  101. NSComparisonResult ca = [@(rc1.origin.y) compare:@(rc2.origin.y)];
  102. if (ca == NSOrderedSame) {
  103. ca = [@(rc1.origin.x) compare:@(rc2.origin.x)];
  104. }
  105. return ca;
  106. }]];
  107. subViews = cells;
  108. }
  109. }else{
  110. // scrollView
  111. if (toView.superview == nil) {
  112. subViews = _parsentView.subviews;
  113. } else if ([[toView.superview subviews] count] >= [ops[UIViewAnimationImages] count]) {
  114. subViews = [toView.superview subviews];
  115. }else{
  116. NSMutableArray *subViewsM = [NSMutableArray array];
  117. subViews = [[self getParsentView:toView maxCount:_photos.count] subviews];
  118. for (UIView *view in subViews) {
  119. if (view.tag >= 1) {
  120. [subViewsM addObject:view];
  121. }
  122. }
  123. for (int i = 0; i < subViews.count; i++) {
  124. if ([(UIView *)subViews[i] tag] == 0) {
  125. if([(UIView*)subViews[i] width] == [(UIView*)[subViewsM firstObject] width] && [subViews[i] isKindOfClass:[[subViewsM firstObject] class]]){
  126. [subViewsM insertObject:subViews[i] atIndex:0];
  127. }
  128. }
  129. }
  130. for (UIView *view in subViews) {
  131. if (view.tag < 1) {
  132. [subViewsM addObject:view];
  133. }
  134. }
  135. subViews = subViewsM;
  136. }
  137. }
  138. __block NSInteger val = [self currentIndexPath].item;
  139. if (collectionView) {
  140. UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:[self currentIndexPath]];
  141. [subViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  142. if ([cell isEqual:obj]) {
  143. val = idx;
  144. *stop = YES;
  145. }
  146. }];
  147. }else if(tableView){
  148. NSIndexPath *minIndexPath = [tableView indexPathForCell: [subViews firstObject]];
  149. NSIndexPath *maxIndexPath = [tableView indexPathForCell: [subViews lastObject]];
  150. val = ([self currentIndexPath].item - minIndexPath.row) % subViews.count;
  151. if ((val == 0 && [self currentIndexPath].item > 0) || [self currentIndexPath].item > subViews.count){
  152. val = subViews.count - 1;
  153. }
  154. if ([self currentIndexPath].item != 0 && maxIndexPath != nil && ([self currentIndexPath].item <= minIndexPath.row || [self currentIndexPath].item > maxIndexPath.row)) {
  155. // 改变动画模式
  156. val = subViews.count + 1;
  157. }
  158. }
  159. CGRect startFrame = CGRectZero;
  160. // 如果点击的图还是一样,并且图片的数量一致的就恢复
  161. if ([options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusZoom) {
  162. toView.hidden = NO;
  163. }
  164. NSInteger ios6NavH = 20;
  165. if (val < subViews.count) {
  166. if (tableView || collectionView) {
  167. // 横屏
  168. if (direction == UICollectionViewScrollDirectionHorizontal) {
  169. // 分页数没改变的情况下, x值就是0
  170. ios6NavH = -20;
  171. startFrame = [_parsentView convertRect:toView.frame toView: options[UIViewAnimationFromView]];
  172. startFrame.origin.y = [ops[UIViewAnimationStartFrame] CGRectValue].origin.y;
  173. startFrame.origin.x = [self currentIndexPath].item * (toView.width + flowLayout.minimumLineSpacing) + collectionView.x - collectionView.contentOffset.x;
  174. } else if(tableView){
  175. UIView *superView = toView;
  176. if ([subViews[val] respondsToSelector:@selector(contentView)]){
  177. for (UIView *view in [[subViews[val] contentView] subviews]) {
  178. if (view.width == toView.width && view.height == toView.height) {
  179. superView = view;
  180. break;
  181. }
  182. }
  183. }else{
  184. superView = subViews[val];
  185. }
  186. startFrame.origin.y = [superView.superview convertRect:superView.frame toView:[self getParsentView:toView]].origin.y;
  187. startFrame.origin.x = [superView.superview convertRect:superView.frame toView:options[UIViewAnimationFromView]].origin.x;
  188. startFrame.size.width = toView.width;
  189. startFrame.size.height = toView.height;
  190. toView.hidden = NO;
  191. }else{
  192. if ([options[UIViewAnimationAnimationStatusType] integerValue] != UIViewAnimationAnimationStatusFade) {
  193. // 竖屏 UICollectionView 九宫格
  194. NSIndexPath *maxIndexPath = [collectionView indexPathForCell:[subViews lastObject]];
  195. NSInteger minRow = [[collectionView indexPathForCell:[subViews firstObject]] item];
  196. if(minRow == 0){
  197. startFrame = [subViews[[[self currentIndexPath] item]] frame];
  198. }else{
  199. NSInteger count = subViews.count - (maxIndexPath.item - [self currentIndexPath].item);
  200. startFrame = [subViews[count-1] frame];
  201. }
  202. startFrame.origin.y -= collectionView.contentOffset.y;
  203. startFrame.size.width = toView.width;
  204. startFrame.size.height = toView.height;
  205. }
  206. if ([options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusZoom) {
  207. [subViews[val] setHidden:YES];
  208. }
  209. }
  210. }else{
  211. // scrollView
  212. startFrame = [subViews[val] frame];
  213. startFrame = [_parsentView convertRect:startFrame toView:options[UIViewAnimationFromView]];
  214. startFrame.size.width = toView.width;
  215. if (
  216. toView.superview == nil && _parsentView
  217. && [options[UIViewAnimationNavigationHeight] isEqual:@(0)]) {
  218. startFrame.origin.y += [self getNavigaitionViewControllerWithView:_parsentView];
  219. }
  220. if ([options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusZoom) {
  221. [subViews[val] setHidden:YES];
  222. }
  223. }
  224. }else{
  225. ops[UIViewAnimationAnimationStatusType] = @(UIViewAnimationAnimationStatusFade);
  226. }
  227. if ([options[UIViewAnimationNavigationHeight] integerValue] > 0) {
  228. startFrame.origin.y += [options[UIViewAnimationNavigationHeight] integerValue];
  229. }
  230. if (!iOS7gt) {
  231. startFrame.origin.y += ios6NavH;
  232. }
  233. if ([options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusRotate) {
  234. if (val < subViews.count) {
  235. [subViews[val] setHidden:NO];
  236. }
  237. toView.hidden = NO;
  238. }
  239. if (subViews.count == 1) {
  240. startFrame.origin.x = [_parsentView convertRect:toView.frame toView:[self getParsentView:options[UIViewAnimationToView]]].origin.x;
  241. }
  242. // startFrame.origin.y += [[self getParsentView:options[UIViewAnimationToView]] frame].origin.y;
  243. if (subViews.count == 1 && subViews.count < [options[UIViewAnimationImages] count]){
  244. ops[UIViewAnimationEndFrame] = options[UIViewAnimationStartFrame];
  245. }else{
  246. ops[UIViewAnimationEndFrame] = [NSValue valueWithCGRect:startFrame];
  247. }
  248. [super restoreWithOptions:ops animation:^{
  249. if (collectionView && flowLayout.scrollDirection == UICollectionViewScrollDirectionHorizontal) {
  250. UIView *cell = [[self getParsentView:_parsentView] hitTest:CGPointMake(startFrame.origin.x, startFrame.origin.y) withEvent:nil];
  251. if ([options[UIViewAnimationAnimationStatusType] integerValue] == UIViewAnimationAnimationStatusZoom) {
  252. [cell setHidden:NO];
  253. }
  254. }
  255. if ([ops[UIViewAnimationAnimationStatusType] integerValue] != UIViewAnimationAnimationStatusFade) {
  256. if (subViews.count > val) {
  257. [subViews[val] setHidden:NO];
  258. }
  259. }
  260. toView.hidden = NO;
  261. subViews = nil;
  262. if (completion) {
  263. completion();
  264. }
  265. }];
  266. }
  267. #pragma mark -
  268. #pragma mark 获取父View
  269. + (UIView *) getParsentView:(UIView *) view maxCount:(NSInteger)maxCount{
  270. NSMutableArray *array = [NSMutableArray array];
  271. for (UIView *childView in [view subviews]) {
  272. if ([childView isKindOfClass:[UIImageView class]]) {
  273. [array addObject:childView];
  274. }
  275. }
  276. if ([[view subviews] count] >= maxCount || view == nil) {
  277. return view;
  278. }
  279. return [self getParsentView:view.superview maxCount:maxCount];
  280. }
  281. #pragma mark - 获取CollectionView
  282. + (UIView *) getCollectionViewWithCell:(UIView *)view{
  283. for (int i = 0; i < view.subviews.count; i++) {
  284. UICollectionViewCell *cell = view.subviews[i];
  285. if ([cell isKindOfClass:[UICollectionViewCell class]] || view == nil) {
  286. return view;
  287. }
  288. }
  289. return [self getCollectionViewWithCell:view.superview];
  290. }
  291. #pragma mark 获取ScrollView
  292. + (UIView *) getScrollViewWithView:(UIView *)view{
  293. if ([view isKindOfClass:[UIScrollView class]] || view == nil) {
  294. return view;
  295. }
  296. return [self getScrollViewWithView:view.superview];
  297. }
  298. #pragma mark 获取TableView
  299. + (UIView *) getTableViewWithView:(UIView *)view{
  300. if ([view.superview isKindOfClass:[UITableView class]]) {
  301. for (UIView *tView in view.superview.subviews) {
  302. if ([tView isKindOfClass:[UITableViewHeaderFooterView class]]) {
  303. return nil;
  304. }
  305. }
  306. }
  307. if ([view isKindOfClass:[UITableView class]] || view == nil) {
  308. return view;
  309. }
  310. return [self getTableViewWithView:view.superview];
  311. }
  312. #pragma mark 获取CollectionView
  313. + (UIView *) getCollectionViewWithView:(UIView *)view{
  314. if ([view isKindOfClass:[UICollectionView class]] || view == nil) {
  315. return view;
  316. }
  317. return [self getCollectionViewWithView:view.superview];
  318. }
  319. #pragma mark - 获取父View
  320. + (UIView *)getParsentView:(UIView *)view{
  321. if ([[view nextResponder] isKindOfClass:[UIViewController class]] || view == nil) {
  322. return view;
  323. }
  324. return [self getParsentView:view.superview];
  325. }
  326. #pragma mark - 通过View获取控制器
  327. + (UIViewController *)getViewControllerWithView:(UIView *)view{
  328. if ([view.nextResponder isKindOfClass:[UIViewController class]] || view == nil) {
  329. return (UIViewController *)view.nextResponder;
  330. }
  331. return [self getViewControllerWithView:view.superview];
  332. }
  333. + (CGFloat)getNavigaitionViewControllerWithView:(UIView *)view{
  334. // 1.判断View是否有导航控制器
  335. if ([[self getViewControllerWithView:view] navigationController] == nil || [[[self getViewControllerWithView:view] navigationController] isNavigationBarHidden]){
  336. return 0;
  337. }
  338. // 2.判断是否是iOS6系统返回导航栏高度
  339. if ([[UIDevice currentDevice].systemVersion floatValue] < 7.0){
  340. return 44;
  341. }
  342. return 64;
  343. }
  344. @end