UGCKitImageScrollerViewController.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // Copyright (c) 2019 Tencent. All rights reserved.
  2. #import "UGCKitImageScrollerViewController.h"
  3. @interface _UGCKitImageScrollerCellView : UICollectionViewCell
  4. @property (readonly, nonatomic) UIImageView *imageView;
  5. @property (readonly, nonatomic) UIButton *closeButton;
  6. @end
  7. static const CGFloat CellSize = 70;
  8. static const CGFloat CloseButtonSize = 20;
  9. typedef _UGCKitImageScrollerCellView CellClass;
  10. @interface UGCKitImageScrollerViewController () <UICollectionViewDelegateFlowLayout>
  11. {
  12. NSMutableArray *_assets;
  13. }
  14. @property (strong, nonatomic) PHCachingImageManager *imageManager;
  15. @end
  16. @implementation UGCKitImageScrollerViewController
  17. static NSString * const reuseIdentifier = @"Cell";
  18. - (instancetype)initWithImageManage:(PHCachingImageManager *)imageManager
  19. {
  20. UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
  21. flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  22. flowLayout.minimumInteritemSpacing = 2;
  23. flowLayout.sectionInset = UIEdgeInsetsMake(0, 8, 0, 8);
  24. if (self = [self initWithCollectionViewLayout:flowLayout]) {
  25. _imageManager = imageManager;
  26. }
  27. return self;
  28. }
  29. - (void)viewDidLoad {
  30. [super viewDidLoad];
  31. _assets = [[NSMutableArray alloc] init];
  32. UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPress:)];
  33. [self.collectionView addGestureRecognizer:longGesture];
  34. [self.collectionView registerClass:[CellClass class] forCellWithReuseIdentifier:reuseIdentifier];
  35. }
  36. #pragma mark - Public
  37. - (void)addAsset:(PHAsset *)asset {
  38. [_assets addObject:asset];
  39. [self.collectionView insertItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:_assets.count-1 inSection:0]]];
  40. }
  41. - (void)removeAssetAtIndex:(NSUInteger)index
  42. {
  43. [_assets removeObjectAtIndex:index];
  44. [self.collectionView deleteItemsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:0]]];
  45. }
  46. #pragma mark <UICollectionViewDataSource>
  47. - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
  48. return 1;
  49. }
  50. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  51. return _assets.count;
  52. }
  53. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  54. CellClass *cell = (CellClass*)[collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
  55. PHAsset *asset = _assets[indexPath.item];
  56. [cell.closeButton setImage:self.closeIcon forState:UIControlStateNormal];
  57. if (cell.closeButton.allTargets.count == 0) {
  58. [cell.closeButton addTarget:self action:@selector(onRemoveItem:) forControlEvents:UIControlEventTouchUpInside];
  59. }
  60. cell.tag = indexPath.item;
  61. [self.imageManager requestImageForAsset:asset
  62. targetSize:cell.imageView.bounds.size
  63. contentMode:PHImageContentModeAspectFill
  64. options:nil
  65. resultHandler:^(UIImage *result, NSDictionary *info) {
  66. if (cell.tag == indexPath.item) {
  67. cell.imageView.image = result;
  68. }
  69. }];
  70. return cell;
  71. }
  72. #pragma mark <UICollectionViewDelegate>
  73. - (CGSize)collectionView:(UICollectionView *)collectionView
  74. layout:(UICollectionViewLayout *)collectionViewLayout
  75. sizeForItemAtIndexPath:(NSIndexPath *)indexPath
  76. {
  77. return CGSizeMake(CellSize+CloseButtonSize/2, CellSize+CloseButtonSize/2);
  78. }
  79. - (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
  80. {
  81. return YES;
  82. }
  83. - (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
  84. {
  85. PHAsset *asset = _assets[sourceIndexPath.item];
  86. [_assets removeObjectAtIndex:sourceIndexPath.item];
  87. [_assets insertObject:asset atIndex:destinationIndexPath.item];
  88. }
  89. #pragma mark - Actions
  90. - (void)onRemoveItem:(UIButton *)button
  91. {
  92. CellClass *cell = (CellClass *)button.superview.superview;
  93. NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
  94. if (indexPath) {
  95. NSUInteger index = indexPath.item;
  96. [self removeAssetAtIndex:index];
  97. if (self.onRemoveHandler) {
  98. self.onRemoveHandler(index);
  99. }
  100. }
  101. }
  102. - (void)onLongPress:(UILongPressGestureRecognizer *)sender {
  103. CGPoint location = [sender locationInView:self.collectionView];
  104. switch (sender.state) {
  105. case UIGestureRecognizerStateBegan: {
  106. NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:location];
  107. [self.collectionView beginInteractiveMovementForItemAtIndexPath:indexPath];
  108. } break;
  109. case UIGestureRecognizerStateChanged:
  110. [self.collectionView updateInteractiveMovementTargetPosition:location];
  111. break;
  112. case UIGestureRecognizerStateEnded:
  113. [self.collectionView endInteractiveMovement];
  114. break;
  115. default:
  116. [self.collectionView cancelInteractiveMovement];
  117. break;
  118. }
  119. }
  120. @end
  121. @implementation _UGCKitImageScrollerCellView
  122. - (instancetype)initWithCoder:(NSCoder *)coder
  123. {
  124. self = [super initWithCoder:coder];
  125. if (self) {
  126. [self commonInit];
  127. }
  128. return self;
  129. }
  130. - (instancetype)initWithFrame:(CGRect)frame
  131. {
  132. self = [super initWithFrame:frame];
  133. if (self) {
  134. [self commonInit];
  135. }
  136. return self;
  137. }
  138. - (void)commonInit {
  139. _imageView = [[UIImageView alloc] initWithFrame:self.contentView.bounds];
  140. _imageView.contentMode = UIViewContentModeScaleAspectFill;
  141. _imageView.clipsToBounds = YES;
  142. _closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
  143. [self.contentView addSubview:_imageView];
  144. [self.contentView addSubview:_closeButton];
  145. }
  146. - (void)layoutSubviews {
  147. [super layoutSubviews];
  148. _imageView.frame = UIEdgeInsetsInsetRect(self.bounds, UIEdgeInsetsMake(CloseButtonSize/2, 0, 0, CloseButtonSize/2));
  149. _closeButton.frame = CGRectMake(0, 0, CloseButtonSize, CloseButtonSize);
  150. _closeButton.center = CGPointMake(CGRectGetMaxX(_imageView.frame), CGRectGetMinY(_imageView.frame));
  151. }
  152. @end