RITLPhotosHorBrowseViewController.m 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. //
  2. // RITLPhotoHorBrowerViewController.m
  3. // RITLPhotoDemo
  4. //
  5. // Created by YueWen on 2018/4/27.
  6. // Copyright © 2018年 YueWen. All rights reserved.
  7. //
  8. #import "RITLPhotosHorBrowseViewController.h"
  9. #import "RITLPhotosBrowseVideoCell.h"
  10. #import "RITLPhotosBrowseImageCell.h"
  11. #import "RITLPhotosBrowseLiveCell.h"
  12. #import "RITLPhotosBottomView.h"
  13. #import "NSBundle+RITLPhotos.h"
  14. #import "PHAsset+RITLPhotos.h"
  15. #import "RITLKit.h"
  16. #import "UIView+RITLFrameChanged.h"
  17. #import "Masonry.h"
  18. #import "RITLPhotosMaker.h"
  19. #import "RITLPhotosDataManager.h"
  20. #import "RITLPhotosConfiguration.h"
  21. #import "UICollectionViewCell+RITLPhotosAsset.h"
  22. #import "UICollectionView+RITLIndexPathsForElements.h"
  23. #import "KKImageEditorViewController.h"
  24. #define RITLPhotosHorBrowseCollectionSpace 3
  25. static NSString *const RITLBrowsePhotoKey = @"photo";
  26. static NSString *const RITLBrowseLivePhotoKey = @"livephoto";
  27. static NSString *const RITLBrowseVideoKey = @"video";
  28. typedef NSString RITLHorBrowseDifferencesKey;
  29. static RITLHorBrowseDifferencesKey *const RITLHorBrowseDifferencesKeyAdded = @"RITLDifferencesKeyAdded";
  30. static RITLHorBrowseDifferencesKey *const RITLHorBrowseDifferencesKeyRemoved = @"RITLDifferencesKeyRemoved";
  31. @interface RITLPhotosHorBrowseViewController ()<UICollectionViewDelegate,UINavigationControllerDelegate,KKImageEditorDelegate>
  32. /// 顶部模拟的导航
  33. @property (nonatomic, strong) UIView *topBar;
  34. /// 返回的按钮
  35. @property (nonatomic, strong) UIButton *backButton;
  36. /// 状态按钮
  37. @property (nonatomic, strong) UIButton *statusButton;
  38. /// 显示索引的标签
  39. @property (strong, nonatomic) IBOutlet UILabel *indexLabel;
  40. /// 展示图片的collectionView
  41. @property (strong, nonatomic) IBOutlet UICollectionView *collectionView;
  42. /// 底部的视图
  43. @property (nonatomic, strong) RITLPhotosBottomView *bottomView;
  44. /// 用于计算缓存的位置
  45. @property (nonatomic, assign) CGRect previousPreheatRect;
  46. /// 预览的collectionView
  47. @property (nonatomic, strong) UICollectionView *browseCollectionView;
  48. // Data
  49. @property (nonatomic, strong) RITLPhotosDataManager *dataManager;
  50. @property (nonatomic, assign) NSInteger cellRow;
  51. @property (nonatomic, strong) RITLPhotosBrowseImageCell *cell; // 记录一下编辑的cell
  52. @property (nonatomic, assign) BOOL isEdit;
  53. @property (nonatomic, strong) PHAsset *asset;
  54. @end
  55. @implementation RITLPhotosHorBrowseViewController
  56. - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  57. {
  58. if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
  59. self.dataManager = RITLPhotosDataManager.sharedInstance;
  60. }
  61. return self;
  62. }
  63. - (void)viewDidLoad
  64. {
  65. [super viewDidLoad];
  66. // Do any additional setup after loading the view.
  67. self.previousPreheatRect = CGRectZero;
  68. [self resetCachedAssets];
  69. self.bottomView = RITLPhotosBottomView.new;
  70. self.bottomView.backgroundColor = [UIColor.blackColor colorWithAlphaComponent:0.8];
  71. // self.bottomView.previewButton.hidden = true;//暂时屏蔽掉图片编辑功能
  72. self.bottomView.isEdit = YES;
  73. [self.bottomView.previewButton addTarget:self
  74. action:@selector(editImage)
  75. forControlEvents:UIControlEventTouchUpInside];
  76. self.bottomView.fullImageButton.selected = self.dataManager.isHightQuality;
  77. [self.bottomView.fullImageButton addTarget:self
  78. action:@selector(hightQualityShouldChanged:)
  79. forControlEvents:UIControlEventTouchUpInside];
  80. [self.bottomView.sendButton addTarget:self
  81. action:@selector(sendButtonDidClick:)
  82. forControlEvents:UIControlEventTouchUpInside];
  83. [self.view addSubview:self.collectionView];
  84. //进行注册
  85. [self.collectionView registerClass:RITLPhotosBrowseImageCell.class forCellWithReuseIdentifier:RITLBrowsePhotoKey];
  86. [self.collectionView registerClass:RITLPhotosBrowseVideoCell.class forCellWithReuseIdentifier:RITLBrowseVideoKey];
  87. if (@available(iOS 9.1,*)) {
  88. [self.collectionView registerClass:RITLPhotosBrowseLiveCell.class forCellWithReuseIdentifier:RITLBrowseLivePhotoKey];
  89. }
  90. //初始化视图
  91. self.topBar = ({
  92. UIView *view = [UIView new];
  93. view.backgroundColor = [UIColor.blackColor colorWithAlphaComponent:0.75];
  94. // view.backgroundColor = THEMECOLOR;
  95. view;
  96. });
  97. self.backButton = ({
  98. UIButton *view = [UIButton new];
  99. view.adjustsImageWhenHighlighted = false;
  100. view.backgroundColor = [UIColor clearColor];
  101. [view addTarget:self action:@selector(pop) forControlEvents:UIControlEventTouchUpInside];
  102. view.imageEdgeInsets = UIEdgeInsetsMake(13, 5, 5, 23);
  103. [view setImage:NSBundle.ritl_browse_back/*@"RITLPhotos.bundle/ritl_browse_back".ritl_image*/ forState:UIControlStateNormal];
  104. view;
  105. });
  106. self.statusButton = ({
  107. UIButton *view = [UIButton new];
  108. view.adjustsImageWhenHighlighted = false;
  109. view.backgroundColor = [UIColor clearColor];
  110. view.imageEdgeInsets = UIEdgeInsetsMake(10, 11, 0, 0);
  111. [view setImage:NSBundle.ritl_brower_selected/*@"RITLPhotos.bundle/ritl_brower_selected".ritl_image*/ forState:UIControlStateNormal];
  112. [view addTarget:self action:@selector(assetStatusDidChanged:) forControlEvents:UIControlEventTouchUpInside];
  113. view;
  114. });
  115. self.indexLabel = ({
  116. UILabel *label = [UILabel new];
  117. label.backgroundColor = RITLColorFromIntRBG(9, 187, 7);
  118. label.text = @"0";
  119. label.font = RITLUtilityFont(RITLFontPingFangSC_Regular, 15);
  120. label.textColor = UIColor.whiteColor;
  121. label.textAlignment = NSTextAlignmentCenter;
  122. label.layer.cornerRadius = 30 / 2.0;
  123. label.layer.masksToBounds = true;
  124. label.hidden = true;
  125. label;
  126. });
  127. [self.view addSubview:self.topBar];
  128. [self.view addSubview:self.bottomView];
  129. [self.view addSubview:self.browseCollectionView];
  130. [self.topBar addSubview:self.backButton];
  131. [self.topBar addSubview:self.statusButton];
  132. [self.topBar addSubview:self.indexLabel];
  133. UIView *lineView = ({
  134. UIView *view = [UIView new];
  135. view.backgroundColor = RITLColorSimpleFromIntRBG(66);
  136. view.frame = @[@0,@79.3,@(RITL_SCREEN_WIDTH),@0.7].ritl_rect;
  137. view;
  138. });
  139. //模拟横线
  140. [self.browseCollectionView addSubview:lineView];
  141. //进行布局
  142. [self.collectionView mas_makeConstraints:^(MASConstraintMaker *make) {
  143. make.top.bottom.offset(0);
  144. make.left.offset(-1 * RITLPhotosHorBrowseCollectionSpace);
  145. make.right.offset(RITLPhotosHorBrowseCollectionSpace);
  146. }];
  147. [self.topBar mas_makeConstraints:^(MASConstraintMaker *make) {
  148. make.left.top.right.offset(0);
  149. make.height.mas_equalTo(RITL_DefaultNaviBarHeight);
  150. }];
  151. [self.backButton mas_makeConstraints:^(MASConstraintMaker *make) {
  152. make.left.offset(15);
  153. make.width.height.mas_equalTo(40);
  154. make.bottom.inset(10);
  155. }];
  156. [self.statusButton mas_makeConstraints:^(MASConstraintMaker *make) {
  157. make.right.inset(15);
  158. make.width.height.mas_equalTo(40);
  159. make.bottom.inset(10);
  160. }];
  161. [self.indexLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  162. make.width.height.mas_equalTo(30);
  163. make.bottom.inset(10);
  164. make.right.inset(15);
  165. }];
  166. [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
  167. make.bottom.left.right.offset(0);
  168. make.height.mas_equalTo(RITL_DefaultTabBarHeight - 3);
  169. }];
  170. [self.browseCollectionView mas_makeConstraints:^(MASConstraintMaker *make) {
  171. make.bottom.equalTo(self.bottomView.mas_top).offset(0);
  172. make.left.right.offset(0);
  173. make.height.mas_equalTo(80);
  174. }];
  175. //如果存在默认方法
  176. if ([self.dataSource respondsToSelector:@selector(defaultItemIndexPath)]) {
  177. [self.collectionView scrollToItemAtIndexPath:self.dataSource.defaultItemIndexPath atScrollPosition:UICollectionViewScrollPositionRight animated:false];
  178. [self updateTopViewWithAsset:[self.dataSource assetAtIndexPath:self.dataSource.defaultItemIndexPath]];
  179. }
  180. // 记录当前控制器的cell.indexPath.row
  181. self.cellRow = self.dataSource.defaultItemIndexPath.row;
  182. //接收cell的单击通知
  183. [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(horBrowseTooBarChangedHiddenStateNotificationationHandler:) name:RITLHorBrowseTooBarChangedHiddenStateNotification object:nil];
  184. //KVO
  185. [self.dataManager addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew context:nil];
  186. [self.dataManager addObserver:self forKeyPath:@"hightQuality" options:NSKeyValueObservingOptionNew context:nil];
  187. //更新发送按钮
  188. [self updateBottomSendButton];
  189. [self updateBrowseCollectionView];
  190. }
  191. - (void)viewWillAppear:(BOOL)animated
  192. {
  193. [super viewWillAppear:animated];
  194. [self.navigationController setNavigationBarHidden:true animated:true];
  195. }
  196. - (void)viewWillDisappear:(BOOL)animated
  197. {
  198. [super viewWillDisappear:animated];
  199. [self.navigationController setNavigationBarHidden:false animated:true];
  200. self.backHandler(self.isEdit,self.asset);
  201. }
  202. - (void)viewDidAppear:(BOOL)animated
  203. {
  204. [super viewDidAppear:animated];
  205. [self updateCachedAssets];
  206. }
  207. - (void)resetCachedAssets
  208. {
  209. [self.dataSource.imageManager stopCachingImagesForAllAssets];
  210. self.previousPreheatRect = CGRectZero;
  211. }
  212. - (void)didReceiveMemoryWarning {
  213. [super didReceiveMemoryWarning];
  214. // Dispose of any resources that can be recreated.
  215. }
  216. - (BOOL)prefersStatusBarHidden
  217. {
  218. return true;
  219. }
  220. - (void)dealloc
  221. {
  222. if (self.isViewLoaded) {
  223. [[NSNotificationCenter defaultCenter] removeObserver:self];
  224. [self.dataManager removeObserver:self forKeyPath:@"count"];
  225. [self.dataManager removeObserver:self forKeyPath:@"hightQuality"];
  226. }
  227. NSLog(@"[%@] is dealloc",NSStringFromClass(self.class));
  228. }
  229. - (void)pop
  230. {
  231. [self.collectionView.visibleCells makeObjectsPerformSelector:@selector(stop)];
  232. [self.navigationController popViewControllerAnimated:true];
  233. }
  234. #pragma mark - Cache
  235. - (void)updateCachedAssets
  236. {
  237. if (!self.isViewLoaded || self.view.window == nil) { return; }
  238. //可视化
  239. CGRect visibleRect = CGRectMake(self.collectionView.ritl_contentOffSetX, self.collectionView.ritl_contentOffSetY, self.collectionView.ritl_width, self.collectionView.ritl_height);
  240. //进行拓展
  241. CGRect preheatRect = CGRectInset(visibleRect, -0.5 * visibleRect.size.width, 0);
  242. //只有可视化的区域与之前的区域有显著的区域变化才需要更新
  243. CGFloat delta = ABS(CGRectGetMidX(preheatRect) - CGRectGetMidX(self.previousPreheatRect));
  244. if (delta <= self.view.ritl_width / 3.0) { return; }
  245. //获得比较后需要进行预加载以及需要停止缓存的区域
  246. NSDictionary *differences = [self differencesBetweenRects:self.previousPreheatRect new:preheatRect];
  247. NSArray <NSValue *> *addedRects = differences[RITLHorBrowseDifferencesKeyAdded];
  248. NSArray <NSValue *> *removedRects = differences[RITLHorBrowseDifferencesKeyRemoved];
  249. ///进行提前缓存的资源
  250. NSArray <PHAsset *> *addedAssets = [[[addedRects ritl_map:^id _Nonnull(NSValue * _Nonnull rectValue) {
  251. return [self.collectionView indexPathsForElementsInRect:rectValue.CGRectValue];
  252. }] ritl_reduce:@[] reduceHandler:^NSArray * _Nonnull(NSArray * _Nonnull result, NSArray <NSIndexPath *>*_Nonnull items) {
  253. return [result arrayByAddingObjectsFromArray:items];
  254. }] ritl_map:^id _Nonnull(NSIndexPath *_Nonnull index) {
  255. return [self.dataSource assetAtIndexPath:index];
  256. }];
  257. ///提前停止缓存的资源
  258. NSArray <PHAsset *> *removedAssets = [[[removedRects ritl_map:^id _Nonnull(NSValue * _Nonnull rectValue) {
  259. return [self.collectionView indexPathsForElementsInRect:rectValue.CGRectValue];
  260. }] ritl_reduce:@[] reduceHandler:^NSArray * _Nonnull(NSArray * _Nonnull result, NSArray <NSIndexPath *>* _Nonnull items) {
  261. return [result arrayByAddingObjectsFromArray:items];
  262. }] ritl_map:^id _Nonnull(NSIndexPath *_Nonnull index) {
  263. return [self.dataSource assetAtIndexPath:index];
  264. }];
  265. CGSize thimbnailSize = ((UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout).itemSize;
  266. //更新缓存
  267. [self.dataSource.imageManager startCachingImagesForAssets:addedAssets targetSize:thimbnailSize contentMode:PHImageContentModeAspectFill options:nil];
  268. [self.dataSource.imageManager stopCachingImagesForAssets:removedAssets targetSize:thimbnailSize contentMode:PHImageContentModeAspectFill options:nil];
  269. //记录当前位置
  270. self.previousPreheatRect = preheatRect;
  271. }
  272. - (NSDictionary <RITLHorBrowseDifferencesKey*,NSArray<NSValue *>*> *)differencesBetweenRects:(CGRect)old new:(CGRect)new
  273. {
  274. if (CGRectIntersectsRect(old, new)) {//如果区域交叉
  275. NSMutableArray <NSValue *> * added = [NSMutableArray arrayWithCapacity:10];
  276. if (CGRectGetMaxX(new) > CGRectGetMaxX(old)) {//表示左滑
  277. [added addObject:[NSValue valueWithCGRect:CGRectMake(CGRectGetMaxX(old), new.origin.y, CGRectGetMaxX(new) - CGRectGetMaxX(old), new.size.height)]];
  278. }
  279. if(CGRectGetMinX(old) > CGRectGetMinX(new)){//表示右滑
  280. [added addObject:[NSValue valueWithCGRect:CGRectMake(CGRectGetMinX(new), new.origin.y, CGRectGetMinX(old) - CGRectGetMinX(new), new.size.height)]];
  281. }
  282. NSMutableArray <NSValue *> * removed = [NSMutableArray arrayWithCapacity:10];
  283. if (CGRectGetMaxX(new) < CGRectGetMaxX(old)) {//表示右滑
  284. [removed addObject:[NSValue valueWithCGRect:CGRectMake(CGRectGetMinX(new), new.origin.y, CGRectGetMaxX(old) - CGRectGetMaxX(new), new.size.height)]];
  285. }
  286. if (CGRectGetMinX(old) < CGRectGetMinX(new)) {//表示左滑
  287. [removed addObject:[NSValue valueWithCGRect:CGRectMake(CGRectGetMinX(new), new.origin.y, CGRectGetMinX(new) - CGRectGetMinX(old), new.size.height)]];
  288. }
  289. return @{RITLHorBrowseDifferencesKeyAdded:added,
  290. RITLHorBrowseDifferencesKeyRemoved:removed};
  291. }else {
  292. return @{RITLHorBrowseDifferencesKeyAdded:@[[NSValue valueWithCGRect:new]],
  293. RITLHorBrowseDifferencesKeyRemoved:@[[NSValue valueWithCGRect:old]]};
  294. }
  295. }
  296. - (void)scrollViewDidScroll:(UIScrollView *)scrollView
  297. {
  298. [self updateCachedAssets];
  299. [self.collectionView.visibleCells makeObjectsPerformSelector:@selector(stop)];
  300. //进行计算当前第几个位置
  301. [self adjustScrollIndexWithContentOffset:scrollView.contentOffset scrollView:scrollView];
  302. }
  303. /// 进行计算当前第几个位置
  304. - (void)adjustScrollIndexWithContentOffset:(CGPoint)contentOffset scrollView:(UIScrollView *)scrollView
  305. {
  306. //根据四舍五入获得的index
  307. NSInteger index = [self indexOfCurrentAsset:scrollView];
  308. self.cellRow = index;
  309. //获得资源
  310. PHAsset *currentAsset = [self.dataSource assetAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
  311. [self updateTopViewWithAsset:currentAsset];
  312. }
  313. /// 根据偏移量获得当前响应到资源
  314. - (NSInteger)indexOfCurrentAsset:(UIScrollView *)scrollView
  315. {
  316. //获得当前正常位置的偏移量
  317. CGFloat contentOffsetX = MIN(MAX(0,scrollView.contentOffset.x),scrollView.contentSize.width);
  318. CGFloat space = 2 * RITLPhotosHorBrowseCollectionSpace;
  319. //根据四舍五入获得的index
  320. NSInteger index = @(round((contentOffsetX + space) * 1.0 / (space + RITL_SCREEN_WIDTH))).integerValue;
  321. return index;
  322. }
  323. #pragma mark - Update View
  324. - (void)updateTopViewWithAsset:(PHAsset *)asset
  325. {
  326. BOOL isSelected = [self.dataManager containAsset:asset];
  327. RITLPhotosConfiguration *configuration = RITLPhotosConfiguration.defaultConfiguration;
  328. if (!configuration.containVideo) { //如果不包含视频
  329. self.statusButton.hidden = (asset.mediaType == PHAssetMediaTypeVideo);
  330. }
  331. if (!configuration.containImage) { //如果不包含图片
  332. self.statusButton.hidden = (asset.mediaType == PHAssetMediaTypeImage);
  333. }
  334. //进行属性隐藏设置
  335. self.indexLabel.hidden = !isSelected;
  336. //视频隐藏编辑功能
  337. self.bottomView.previewButton.hidden = (asset.mediaType == PHAssetMediaTypeVideo);
  338. if (isSelected) {
  339. self.indexLabel.text = @([self.dataManager.assetIdentiers indexOfObject:asset.localIdentifier] + 1).stringValue;
  340. }
  341. }
  342. /// 更新发送按钮
  343. - (void)updateBottomSendButton
  344. {
  345. NSInteger count = self.dataManager.count;
  346. UIControlState state = (count == 0 ? UIControlStateDisabled : UIControlStateNormal);
  347. NSString *title;
  348. if (!RITLPhotosConfiguration.defaultConfiguration.isRichScan) {
  349. title = (count == 0 ? Localized(@"JX_Send") : [NSString stringWithFormat:@"%@(%@)",Localized(@"JX_Send"),@(count)]);
  350. }else {
  351. title = Localized(@"JX_Finish");
  352. }
  353. self.bottomView.sendButton.enabled = !(count == 0);
  354. [self.bottomView.sendButton setTitle:title forState:state];
  355. }
  356. /// 更新排版集合视图的状态
  357. - (void)updateBrowseCollectionView
  358. {
  359. // NSInteger count = self.dataManager.count;
  360. // self.browseCollectionView.hidden = (count == 0);
  361. }
  362. #pragma mark - Getter
  363. -(UICollectionView *)collectionView
  364. {
  365. if (_collectionView == nil)
  366. {
  367. UICollectionViewFlowLayout * flowLayout = [[UICollectionViewFlowLayout alloc]init];
  368. flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  369. flowLayout.minimumLineSpacing = 2 * RITLPhotosHorBrowseCollectionSpace;
  370. flowLayout.sectionInset = UIEdgeInsetsMake(0, RITLPhotosHorBrowseCollectionSpace, 0, RITLPhotosHorBrowseCollectionSpace);
  371. flowLayout.itemSize = @[@(RITL_SCREEN_WIDTH),@(RITL_SCREEN_HEIGHT)].ritl_size;
  372. _collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(-1 * RITLPhotosHorBrowseCollectionSpace, 0, self.ritl_width + 2 * RITLPhotosHorBrowseCollectionSpace, self.ritl_height) collectionViewLayout:flowLayout];
  373. _collectionView.backgroundColor = UIColor.blackColor;
  374. //初始化collectionView属性
  375. _collectionView.dataSource = self.dataSource;
  376. _collectionView.delegate = self;
  377. _collectionView.pagingEnabled = true;
  378. _collectionView.showsHorizontalScrollIndicator = false;
  379. //不使用自动适配
  380. if (@available(iOS 11.0,*)) {
  381. _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
  382. }
  383. }
  384. return _collectionView;
  385. }
  386. - (UICollectionView *)browseCollectionView
  387. {
  388. if (_browseCollectionView == nil)
  389. {
  390. UICollectionViewFlowLayout * flowLayout = [[UICollectionViewFlowLayout alloc]init];
  391. flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
  392. // flowLayout.minimumLineSpacing = 2 * RITLPhotosHorBrowseCollectionSpace;
  393. // flowLayout.sectionInset = UIEdgeInsetsMake(0, RITLPhotosHorBrowseCollectionSpace, 0, RITLPhotosHorBrowseCollectionSpace);
  394. // flowLayout.itemSize = @[@(RITL_SCREEN_WIDTH),@(RITL_SCREEN_HEIGHT)].ritl_size;
  395. _browseCollectionView = [[UICollectionView alloc]initWithFrame:@[].ritl_rect collectionViewLayout:flowLayout];
  396. _browseCollectionView.backgroundColor = self.bottomView.backgroundColor;
  397. //初始化collectionView属性
  398. // _browseCollectionView.dataSource = self.dataSource;
  399. // _browseCollectionView.delegate = self;
  400. _browseCollectionView.hidden = true;
  401. _browseCollectionView.pagingEnabled = true;
  402. _browseCollectionView.showsHorizontalScrollIndicator = false;
  403. //不使用自动适配
  404. if (@available(iOS 11.0,*)) {
  405. _browseCollectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
  406. }
  407. }
  408. return _browseCollectionView;
  409. }
  410. #pragma mark - Notification
  411. - (void)horBrowseTooBarChangedHiddenStateNotificationationHandler:(NSNotification *)notification
  412. {
  413. NSNumber *hiddenResult = [notification.userInfo valueForKey:@"hidden"];
  414. if (hiddenResult) {//存在控制
  415. /*self.browseCollectionView.hidden = */self.topBar.hidden = self.bottomView.hidden = hiddenResult.boolValue;
  416. if (hiddenResult.boolValue == false) {//如果是显示,需要更新状态
  417. [self updateBrowseCollectionView];
  418. }
  419. }else {
  420. BOOL beforeStatus = self.topBar.hidden;
  421. /*self.browseCollectionView.hidden = */self.topBar.hidden = self.bottomView.hidden = !beforeStatus;
  422. if (beforeStatus) {//如果是需要展示
  423. [self updateBrowseCollectionView];
  424. }
  425. }
  426. }
  427. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
  428. {
  429. if ([keyPath isEqualToString:@"count"] && [object isEqual:self.dataManager]) {
  430. // 预览功能现在是屏蔽状态
  431. //self.bottomView.previewButton.enabled = !(count == 0);
  432. //发送按钮
  433. [self updateBottomSendButton];
  434. //选中的排版视图
  435. [self updateBrowseCollectionView];
  436. }
  437. else if([keyPath isEqualToString:@"hightQuality"] && [object isEqual:self.dataManager]){
  438. BOOL hightQuality = [change[NSKeyValueChangeNewKey] boolValue];
  439. self.bottomView.fullImageButton.selected = hightQuality;
  440. }
  441. }
  442. #pragma mark - action
  443. - (void)editImage {
  444. self.isEdit = NO;
  445. self.cell = (RITLPhotosBrowseImageCell *)[self.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:self.cellRow inSection:0]];
  446. KKImageEditorViewController *editor = [[KKImageEditorViewController alloc] initWithImage:self.cell.imageView.image delegate:self];
  447. editor.asset = [self.dataSource assetAtIndexPath:[NSIndexPath indexPathForRow:self.cellRow inSection:0]];
  448. UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:editor];
  449. [self presentViewController:vc animated:YES completion:nil];
  450. }
  451. - (void)hightQualityShouldChanged:(UIButton *)sender
  452. {
  453. self.dataManager.hightQuality = !self.dataManager.hightQuality;
  454. }
  455. - (void)sendButtonDidClick:(UIButton *)sender
  456. {
  457. [RITLPhotosMaker.sharedInstance startMakePhotosComplete:^{
  458. [self.collectionView.visibleCells makeObjectsPerformSelector:@selector(stop)];
  459. [self.navigationController dismissViewControllerAnimated:true completion:nil];
  460. }];
  461. }
  462. - (void)assetStatusDidChanged:(UIButton *)sender
  463. {
  464. //获得当前的资源
  465. PHAsset *asset = [self.dataSource assetAtIndexPath:[NSIndexPath indexPathForItem:[self indexOfCurrentAsset:self.collectionView] inSection:0]];
  466. if (self.dataManager.count >= RITLPhotosConfiguration.defaultConfiguration.maxCount &&
  467. ![self.dataManager containAsset:asset]/*是添加*/) {
  468. [g_server showMsg:Localized(@"JX_CannotSelectMorePhotos")];
  469. return;
  470. }//不能进行选择
  471. //进行修正
  472. [self.dataManager addOrRemoveAsset:asset];
  473. //更新top
  474. [self updateTopViewWithAsset:asset];
  475. }
  476. #pragma mark- 照片编辑后的回调
  477. - (void)imageDidFinishEdittingWithImage:(UIImage *)image asset:(PHAsset *)asset
  478. {
  479. self.cell.imageView.image = image;
  480. self.isEdit = YES;
  481. self.asset = asset;
  482. [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
  483. [PHAssetChangeRequest creationRequestForAssetFromImage:image];
  484. } completionHandler:^(BOOL success, NSError * _Nullable error) {
  485. if (error) {
  486. NSLog(@"%@",@"保存失败");
  487. [JXMyTools showTipView:@"图片编辑失败"];
  488. } else {
  489. NSLog(@"%@",@"保存成功");
  490. dispatch_async(dispatch_get_main_queue(), ^{
  491. [self.navigationController popToRootViewControllerAnimated:YES];
  492. });
  493. }
  494. }];
  495. }
  496. @end