XG_AssetPickerController.m 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720
  1. //
  2. // XG_AssetPickerController.m
  3. // MyApp
  4. //
  5. // Created by huxinguang on 2018/9/26.
  6. // Copyright © 2018年 huxinguang. All rights reserved.
  7. //
  8. #import "XG_AssetPickerController.h"
  9. #import "XG_AssetCell.h"
  10. #import "XG_TitleView.h"
  11. #import "XG_BarButton.h"
  12. #import "XG_AlbumCell.h"
  13. #import <MobileCoreServices/MobileCoreServices.h>
  14. #import "XG_MediaBrowseView.h"
  15. #import "FLAnimatedImage.h"
  16. @interface XG_AssetPickerController ()<UICollectionViewDataSource,UICollectionViewDelegate,UITableViewDelegate,UITableViewDataSource,UINavigationControllerDelegate, UIImagePickerControllerDelegate,PHPhotoLibraryChangeObserver>
  17. @property (nonatomic, strong) UICollectionView *collectionView;
  18. @property (nonatomic, strong) NSMutableArray<XG_AssetModel *> *assetArr;
  19. @property (nonatomic, strong) UIButton *bottomConfirmBtn;
  20. @property (nonatomic, strong) UITableView *albumTableView;
  21. @property (nonatomic, strong) UIView *containerView;
  22. @property (nonatomic, strong) NSMutableArray<XG_AlbumModel *> *albumArr;
  23. @property (nonatomic, strong) UIControl *mask;
  24. @property (nonatomic, strong) NavTitleView *ntView;
  25. @property (nonatomic, assign) CGFloat containerViewHeight;
  26. @property (nonatomic, strong) NSIndexPath *currentAlbumIndexpath;
  27. @property (nonatomic, strong) XG_AssetModel *placeholderModel; //相机占位model
  28. @property (nonatomic, strong) NSMutableArray<NSIndexPath *> *albumSelectedIndexpaths;
  29. @property (nonatomic, strong) NSLayoutConstraint *containerView_bottom;
  30. @property (nonatomic, assign) BOOL hideStatusBar;
  31. @property (nonatomic, strong) NSTimer * timer;
  32. @property (nonatomic) int numTime;
  33. @end
  34. @implementation XG_AssetPickerController
  35. @synthesize assetArr = _assetArr;//同时重写setter/getter方法需要这样
  36. -(XG_AssetModel *)placeholderModel{
  37. if (_placeholderModel == nil) {
  38. _placeholderModel = [[XG_AssetModel alloc]init];
  39. _placeholderModel.isPlaceholder = YES;
  40. }
  41. return _placeholderModel;
  42. }
  43. -(NSMutableArray<XG_AlbumModel *> *)albumArr{
  44. if (_albumArr == nil) _albumArr = [NSMutableArray array];
  45. return _albumArr;
  46. }
  47. -(NSMutableArray<XG_AssetModel *> *)assetArr{
  48. if (_assetArr == nil) _assetArr = [NSMutableArray array];
  49. return _assetArr;
  50. }
  51. - (NSMutableArray<NSIndexPath *> *)albumSelectedIndexpaths{
  52. if (_albumSelectedIndexpaths == nil) _albumSelectedIndexpaths = [NSMutableArray array];
  53. return _albumSelectedIndexpaths;
  54. }
  55. -(void)setAssetArr:(NSMutableArray<XG_AssetModel *> *)assetArr{
  56. _assetArr = assetArr;
  57. //插入相机占位
  58. if (![_assetArr containsObject:self.placeholderModel]) {
  59. [_assetArr insertObject:self.placeholderModel atIndex:0];
  60. }
  61. }
  62. -(void)dealloc{
  63. [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
  64. [[NSNotificationCenter defaultCenter] removeObserver:self];
  65. }
  66. -(instancetype)initWithOptions:(XG_AssetPickerOptions *)options delegate:(id<XG_AssetPickerControllerDelegate>)delegate{
  67. if (self = [super init]) {
  68. self.pickerOptions = options;
  69. self.delegate = delegate;
  70. }
  71. return self;
  72. }
  73. //- (BOOL)prefersStatusBarHidden{
  74. // return self.hideStatusBar;
  75. //}
  76. - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation{
  77. return UIStatusBarAnimationFade;
  78. }
  79. - (void)viewDidLoad {
  80. [super viewDidLoad];
  81. self.view.backgroundColor = [UIColor whiteColor];
  82. [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
  83. // [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(updateStatusBar) name:kShowStatusBarNotification object:nil];
  84. [self configMask];
  85. [self getAlbums];
  86. }
  87. - (void)getAlbums{
  88. @weakify(self)
  89. [[XG_AssetPickerManager manager] getAllAlbums:self.pickerOptions.videoPickable completion:^(NSArray<XG_AlbumModel *> *models) {
  90. @strongify(self)
  91. if (!self) return;
  92. self.albumArr = [NSMutableArray arrayWithArray:models];
  93. self.albumArr[0].isSelected = YES;//默认第一个选中
  94. [self.ntView resetViewWithStr:self.albumArr[0].name];
  95. self.currentAlbumIndexpath = [NSIndexPath indexPathForRow:0 inSection:0];
  96. self.assetArr = self.albumArr[0].assetArray;
  97. [self refreshAlbumAssetsStatus];
  98. [self configCollectionView];
  99. [self configBottomConfirmBtn];
  100. [self configAlbumTableView];
  101. [self addConstraints];
  102. [self.collectionView reloadData];
  103. [self refreshNavRightBtn];
  104. [self.albumTableView reloadData];
  105. }];
  106. }
  107. - (void)resetAlbums{
  108. @weakify(self)
  109. [[XG_AssetPickerManager manager] getAllAlbums:self.pickerOptions.videoPickable completion:^(NSArray<XG_AlbumModel *> *models) {
  110. @strongify(self)
  111. if (!self) return;
  112. self.albumArr = [NSMutableArray arrayWithArray:models];
  113. self.albumArr[self.currentAlbumIndexpath.row].isSelected = YES;
  114. [self.ntView resetViewWithStr:self.albumArr[self.currentAlbumIndexpath.row].name];
  115. self.assetArr = self.albumArr[self.currentAlbumIndexpath.row].assetArray;
  116. [self refreshAlbumAssetsStatus];
  117. [self refreshNavRightBtn];
  118. [self refreshBottomConfirmBtn];
  119. [self.albumTableView reloadData];
  120. }];
  121. }
  122. - (void)configMask{
  123. self.mask = [UIControl new];
  124. self.mask.frame = self.view.bounds;
  125. self.mask.backgroundColor = [UIColor clearColor];
  126. self.mask.userInteractionEnabled = NO;
  127. [self.view addSubview:self.mask];
  128. [self.mask addTarget:self action:@selector(onClickMask) forControlEvents:UIControlEventTouchUpInside];
  129. }
  130. - (void)configTitleView{
  131. self.ntView = [[NavTitleView alloc]init];
  132. self.ntView.frame = CGRectMake(0, STATUSBAR_HEIGHT, SCREEN_WIDTH, NAVIGATIONBAR_HEIGHT - STATUSBAR_HEIGHT);
  133. self.ntView.titleBtn.selected = NO;
  134. [self.ntView.titleBtn addTarget:self action:@selector(onTitleBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  135. WEAKSELF
  136. self.ntView.blockRight = ^{
  137. [weakSelf onConfirmBtnClick];
  138. };
  139. self.ntView.blockLeft = ^{
  140. [weakSelf onLeftBarButtonClick];
  141. };
  142. [self.view addSubview:self.ntView];
  143. }
  144. //取消
  145. - (void)onLeftBarButtonClick{
  146. if (self.delegate && [self.delegate respondsToSelector:@selector(assetPickerControllerDidCancel:)]) {
  147. [self.delegate assetPickerControllerDidCancel:self];
  148. }
  149. [GB_Nav popViewControllerAnimated:true];
  150. }
  151. - (void)configCollectionView {
  152. if (!self.collectionView) {
  153. UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
  154. CGFloat itemWH = (self.view.frame.size.width - (kItemsAtEachLine-1)*kItemMargin)/kItemsAtEachLine;
  155. layout.itemSize = CGSizeMake(itemWH, itemWH);
  156. layout.minimumInteritemSpacing = kItemMargin;
  157. layout.minimumLineSpacing = kItemMargin;
  158. self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
  159. self.collectionView.backgroundColor = [UIColor whiteColor];
  160. self.collectionView.dataSource = self;
  161. self.collectionView.delegate = self;
  162. self.collectionView.alwaysBounceVertical = YES;
  163. [self.view addSubview:self.collectionView];
  164. [self.collectionView registerNib:[UINib nibWithNibName:@"XG_AssetCell" bundle:nil] forCellWithReuseIdentifier:@"XG_AssetCell"];
  165. }
  166. }
  167. - (void)configAlbumTableView{
  168. if (!self.albumTableView) {
  169. self.containerViewHeight = SCREEN_HEIGHT-NAVIGATIONBAR_HEIGHT;
  170. self.containerView = [UIView new];
  171. self.containerView.backgroundColor = [UIColor whiteColor];
  172. [self.view addSubview:self.containerView];
  173. self.albumTableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain];
  174. self.albumTableView.delegate = self;
  175. self.albumTableView.dataSource = self;
  176. self.albumTableView.rowHeight = kAlbumTableViewRowHeight;
  177. self.albumTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  178. [self.containerView addSubview:self.albumTableView];
  179. }
  180. }
  181. - (void)configBottomConfirmBtn {
  182. if (!self.bottomConfirmBtn) {
  183. self.bottomConfirmBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  184. self.bottomConfirmBtn.backgroundColor = [UIColor whiteColor];
  185. self.bottomConfirmBtn.titleLabel.font = [UIFont boldSystemFontOfSize:kBottomConfirmBtnTitleFontSize];
  186. // [self.bottomConfirmBtn addTarget:self action:@selector(onConfirmBtnClick) forControlEvents:UIControlEventTouchUpInside];
  187. // [self.bottomConfirmBtn setTitle:[NSString stringWithFormat:@"确定(%d/%d)",(int)self.pickerOptions.pickedAssetModels.count,(int)self.pickerOptions.maxAssetsCount] forState:UIControlStateNormal];
  188. [self.bottomConfirmBtn setTitleColor:kAppThemeColor forState:UIControlStateNormal];
  189. [self.bottomConfirmBtn setTitleColor:[UIColor lightGrayColor] forState:UIControlStateDisabled];
  190. if (self.pickerOptions.pickedAssetModels.count > 0) {
  191. self.bottomConfirmBtn.enabled = YES;
  192. }else{
  193. self.bottomConfirmBtn.enabled = NO;
  194. }
  195. [self.view addSubview:self.bottomConfirmBtn];
  196. }
  197. }
  198. - (void)addConstraints{
  199. self.collectionView.translatesAutoresizingMaskIntoConstraints = NO;
  200. self.bottomConfirmBtn.translatesAutoresizingMaskIntoConstraints = NO;
  201. self.containerView.translatesAutoresizingMaskIntoConstraints = NO;
  202. self.albumTableView.translatesAutoresizingMaskIntoConstraints = NO;
  203. self.containerView_bottom = [NSLayoutConstraint constraintWithItem:self.containerView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
  204. [NSLayoutConstraint activateConstraints:@[
  205. // collectionView约束
  206. [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:kAppStatusBarAndNavigationBarHeight],
  207. [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0],
  208. [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.bottomConfirmBtn attribute:NSLayoutAttributeTop multiplier:1.0 constant:0],
  209. [NSLayoutConstraint constraintWithItem:self.collectionView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0],
  210. // bottomConfirmBtn约束
  211. [NSLayoutConstraint constraintWithItem:self.bottomConfirmBtn attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0],
  212. [NSLayoutConstraint constraintWithItem:self.bottomConfirmBtn attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0],
  213. [NSLayoutConstraint constraintWithItem:self.bottomConfirmBtn attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-kAppTabbarSafeBottomMargin],
  214. [NSLayoutConstraint constraintWithItem:self.bottomConfirmBtn attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:kBottomConfirmBtnHeight],
  215. // containerView约束
  216. [NSLayoutConstraint constraintWithItem:self.containerView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0],
  217. self.containerView_bottom,
  218. [NSLayoutConstraint constraintWithItem:self.containerView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0],
  219. [NSLayoutConstraint constraintWithItem:self.containerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:self.containerViewHeight],
  220. // albumTableView约束
  221. [NSLayoutConstraint constraintWithItem:self.albumTableView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeTop multiplier:1.0 constant:kAlbumTableViewMarginTopBottom],
  222. [NSLayoutConstraint constraintWithItem:self.albumTableView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0],
  223. [NSLayoutConstraint constraintWithItem:self.albumTableView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-kAlbumTableViewMarginTopBottom],
  224. [NSLayoutConstraint constraintWithItem:self.albumTableView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.containerView attribute:NSLayoutAttributeRight multiplier:1.0 constant:0]
  225. ]];
  226. }
  227. //下一步
  228. - (void)onConfirmBtnClick {
  229. [self timerStop];
  230. [MBProgressHUD showHUDAddedTo:self.view animated:YES];
  231. //启动定时器
  232. self.numTime = 0;
  233. [self timerStart];
  234. NSLog(@"1---");
  235. }
  236. #pragma mark 定时器相关
  237. - (void)timerStart{
  238. //开启定时器
  239. if (_timer == nil) {
  240. _timer =[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
  241. }
  242. }
  243. - (void)timerRun{
  244. //每秒的动作
  245. if (_numTime <=0) {
  246. //刷新按钮 开始
  247. [self timerStop];
  248. if (self.delegate && [self.delegate respondsToSelector:@selector(assetPickerController:didFinishPickingAssets:)]) {
  249. [self.delegate assetPickerController:self didFinishPickingAssets:[self.pickerOptions.pickedAssetModels copy]];
  250. }
  251. NSLog(@"2---");
  252. [GB_Nav popViewControllerAnimated:true];
  253. NSLog(@"3---");
  254. return;
  255. }
  256. _numTime --;
  257. }
  258. - (void)timerStop{
  259. //停止定时器
  260. if (_timer != nil) {
  261. [_timer invalidate];
  262. self.timer = nil;
  263. }
  264. [MBProgressHUD hideHUDForView:self.view animated:YES];
  265. }
  266. //标题
  267. - (void)onTitleBtnClick:(UIButton *)btn{
  268. btn.selected = !btn.selected;
  269. if (btn.selected) {
  270. self.containerView_bottom.constant = self.containerViewHeight + kAppStatusBarAndNavigationBarHeight;
  271. [self.view insertSubview:self.mask belowSubview:self.containerView];
  272. self.mask.userInteractionEnabled = YES;
  273. }else{
  274. self.containerView_bottom.constant = -self.containerViewHeight;
  275. self.mask.userInteractionEnabled = NO;
  276. }
  277. [self.albumTableView reloadData];
  278. [UIView animateWithDuration:0.35 animations:^{
  279. if (btn.selected) {
  280. CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
  281. self.ntView.arrowView.transform = transform;
  282. self.mask.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.2];
  283. }else{
  284. self.ntView.arrowView.transform = CGAffineTransformIdentity;
  285. self.mask.backgroundColor = [UIColor clearColor];
  286. }
  287. [self.view layoutIfNeeded];
  288. } completion:^(BOOL finished) {
  289. [self.albumTableView scrollToRowAtIndexPath:self.currentAlbumIndexpath atScrollPosition:UITableViewScrollPositionNone animated:NO];
  290. if (!btn.selected) {
  291. [self.view insertSubview:self.mask belowSubview:self.collectionView];
  292. }
  293. }];
  294. }
  295. - (void)onClickMask{
  296. [self onTitleBtnClick:self.ntView.titleBtn];
  297. }
  298. #pragma mark - UICollectionViewDataSource && Delegate
  299. - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
  300. return self.assetArr.count;
  301. }
  302. - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
  303. XG_AssetCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"XG_AssetCell" forIndexPath:indexPath];
  304. XG_AssetModel *model = self.assetArr[indexPath.row];
  305. cell.model = model;
  306. __weak typeof(cell) weakCell = cell;
  307. @weakify(self)
  308. cell.didSelectPhotoBlock = ^(BOOL isSelected) {
  309. @strongify(self)
  310. if (!self) return;
  311. if (isSelected) {
  312. // 1. 取消选择
  313. weakCell.selectPhotoButton.selected = NO;
  314. model.picked = NO;
  315. model.number = 0;
  316. for (XG_AssetModel *am in [self.pickerOptions.pickedAssetModels copy]) {
  317. if ([am.asset.localIdentifier isEqualToString:model.asset.localIdentifier]) {
  318. am.number = 0;
  319. am.picked = NO;
  320. [self.pickerOptions.pickedAssetModels removeObject:am];
  321. }
  322. }
  323. weakCell.numberLabel.text = @"";
  324. } else {
  325. // 2. 选择照片,检查是否超过了最大个数的限制
  326. if (self.pickerOptions.pickedAssetModels.count < self.pickerOptions.maxAssetsCount) {
  327. weakCell.selectPhotoButton.selected = YES;
  328. model.picked = YES;
  329. [self.pickerOptions.pickedAssetModels addObject:model];
  330. weakCell.numberLabel.text = [NSString stringWithFormat:@"%d",(int)self.pickerOptions.pickedAssetModels.count];
  331. } else {
  332. [GlobalMethod showAlert:[NSString stringWithFormat:@"最多选择%d张照片",(int)self.pickerOptions.maxAssetsCount]];
  333. }
  334. }
  335. [self refreshAlbumAssetsStatus];
  336. //取消选择的时候才刷新所有选中的item
  337. if (self.albumSelectedIndexpaths.count > 0 && isSelected) {
  338. [collectionView reloadItemsAtIndexPaths:self.albumSelectedIndexpaths];
  339. }
  340. [self refreshNavRightBtn];
  341. [self refreshBottomConfirmBtn];
  342. };
  343. return cell;
  344. }
  345. - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
  346. if (indexPath.item == 0) {
  347. //打开相机
  348. if (self.pickerOptions.pickedAssetModels.count < self.pickerOptions.maxAssetsCount) {
  349. #if TARGET_OS_SIMULATOR
  350. [GlobalMethod showAlert:@"模拟器不支持相机"];
  351. #else
  352. [self openCamera];
  353. #endif
  354. }else{
  355. [GlobalMethod showAlert:[NSString stringWithFormat:@"最多选择%d张照片",(int)self.pickerOptions.maxAssetsCount]];
  356. }
  357. }else{
  358. NSMutableArray *items = [self.assetArr mutableCopy];
  359. [items removeObjectAtIndex:0];
  360. // [self performSelector:@selector(updateStatusBar) withObject:nil afterDelay:0.2];
  361. XG_MediaBrowseView *v = [[XG_MediaBrowseView alloc] initWithItems:items];
  362. [v presentCellImageAtIndexPath:indexPath FromCollectionView:collectionView toContainer:self.navigationController.view animated:YES completion:nil];
  363. }
  364. }
  365. #pragma mark - UITableViewDelegate,UITableViewDataSource
  366. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  367. return self.albumArr.count;
  368. }
  369. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  370. static NSString *cellIdentifier = @"CellIdentifier";
  371. XG_AlbumCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
  372. if (!cell) {
  373. cell = [[[NSBundle mainBundle]loadNibNamed:@"XG_AlbumCell" owner:self options:nil] lastObject];
  374. }
  375. cell.model = self.albumArr[indexPath.row];
  376. return cell;
  377. }
  378. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
  379. for (XG_AlbumModel *album in self.albumArr) {
  380. album.isSelected = NO;
  381. }
  382. self.albumArr[indexPath.row].isSelected = YES;
  383. [self.ntView resetViewWithStr:self.albumArr[indexPath.row].name];
  384. self.assetArr = self.albumArr[indexPath.row].assetArray;
  385. if (indexPath != self.currentAlbumIndexpath) {
  386. [self refreshAlbumAssetsStatus];
  387. [self.collectionView reloadData];
  388. [self onTitleBtnClick:self.ntView.titleBtn];
  389. }else{
  390. [self onTitleBtnClick:self.ntView.titleBtn];
  391. }
  392. self.currentAlbumIndexpath = indexPath;
  393. }
  394. - (void)refreshAlbumAssetsStatus{
  395. [self.albumSelectedIndexpaths removeAllObjects];
  396. for (int i=1; i<self.assetArr.count; i++) {//第1个为相机占位
  397. XG_AssetModel *am = self.assetArr[i];
  398. am.picked = NO;
  399. am.number = 0;
  400. for (int j=0; j<self.pickerOptions.pickedAssetModels.count; j++) {
  401. XG_AssetModel *pam = self.pickerOptions.pickedAssetModels[j];
  402. if ([am.asset.localIdentifier isEqualToString:pam.asset.localIdentifier]) {
  403. am.picked = YES;
  404. am.number = j+1;
  405. [self.albumSelectedIndexpaths addObject:[NSIndexPath indexPathForItem:i inSection:0]];
  406. }
  407. }
  408. }
  409. }
  410. - (void)refreshNavRightBtn{
  411. XG_BarButton *btn = (XG_BarButton *)self.navigationItem.rightBarButtonItem.customView;
  412. if (self.pickerOptions.pickedAssetModels.count > 0) {
  413. btn.enabled = YES;
  414. }else{
  415. btn.enabled = NO;
  416. }
  417. }
  418. - (void)refreshBottomConfirmBtn {
  419. if (self.pickerOptions.pickedAssetModels.count > 0) {
  420. self.bottomConfirmBtn.enabled = YES;
  421. }else{
  422. self.bottomConfirmBtn.enabled = NO;
  423. }
  424. // [self.bottomConfirmBtn setTitle:[NSString stringWithFormat:@"确定(%d/%d)",(int)self.pickerOptions.pickedAssetModels.count,(int)self.pickerOptions.maxAssetsCount] forState:UIControlStateNormal];
  425. }
  426. //- (void)updateStatusBar{
  427. // self.hideStatusBar = !self.hideStatusBar;
  428. // [self performSelectorOnMainThread:@selector(setNeedsStatusBarAppearanceUpdate) withObject:nil waitUntilDone:YES];
  429. //}
  430. - (void)showHudWithString:(NSString *)string{
  431. }
  432. - (void)openCamera{
  433. UIImagePickerController *picker = [[UIImagePickerController alloc] init];
  434. picker.sourceType = UIImagePickerControllerSourceTypeCamera;
  435. if (self.pickerOptions.videoPickable) {
  436. NSString *mediaTypeImage = (NSString *)kUTTypeImage;
  437. NSString *mediaTypeMovie = (NSString *)kUTTypeMovie;
  438. picker.mediaTypes = @[mediaTypeImage,mediaTypeMovie];
  439. }
  440. picker.delegate = self;
  441. picker.navigationBar.barTintColor = self.navigationController.navigationBar.barTintColor;
  442. picker.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor],
  443. NSFontAttributeName : [UIFont boldSystemFontOfSize:18]};
  444. [self presentViewController:picker animated:YES completion:nil];
  445. }
  446. - (void)switchToCameraRoll{
  447. for (XG_AlbumModel *album in self.albumArr) {
  448. album.isSelected = NO;
  449. }
  450. self.albumArr[0].isSelected = YES;
  451. // [self.ntView.titleBtn setTitle:self.albumArr[0].name forState:UIControlStateNormal];
  452. [self.ntView resetViewWithStr:self.albumArr[0].name];
  453. // self.ntView.titleBtnWidth = [self getTitleBtnWidthWithTitle:self.albumArr[0].name];
  454. self.assetArr = self.albumArr[0].assetArray;
  455. [self refreshAlbumAssetsStatus];
  456. [self.collectionView reloadData];
  457. [self.albumTableView reloadData];
  458. self.currentAlbumIndexpath = [NSIndexPath indexPathForRow:0 inSection:0];
  459. }
  460. - (CGFloat)getTitleBtnWidthWithTitle:(NSString *)title{
  461. NSMutableDictionary *attr = [NSMutableDictionary new];
  462. attr[NSFontAttributeName] = kTitleViewTitleFont;
  463. CGRect rect = [title boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT)
  464. options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
  465. attributes:attr context:nil];
  466. return rect.size.width + kTitleViewTextImageDistance + kTitleViewArrowSize.width;
  467. }
  468. #pragma mark - PHPhotoLibraryChangeObserver
  469. - (void)photoLibraryDidChange:(PHChange *)changeInstance{
  470. @weakify(self)
  471. dispatch_sync(dispatch_get_main_queue(), ^{
  472. @strongify(self)
  473. if (!self) return;
  474. //相册添加照片所产生的change(这里只对app内调用相机拍照后点击“use photo(使用照片)”按钮后所产生的change)
  475. XG_AlbumModel *currentAlbum = self.albumArr[0];
  476. PHFetchResultChangeDetails *changes = [changeInstance changeDetailsForFetchResult:currentAlbum.result];
  477. if (changes) {
  478. currentAlbum.result = [changes fetchResultAfterChanges];
  479. if (changes.hasIncrementalChanges) {
  480. if (self.collectionView) {
  481. NSArray<PHAsset *> *insertItems = changes.insertedObjects;
  482. NSMutableArray *indexPaths = @[].mutableCopy;
  483. if (insertItems && insertItems.count > 0) {
  484. for (int i=0; i<insertItems.count; i++) {
  485. XG_AssetModel *model = [[XG_AssetModel alloc] init];
  486. model.asset = insertItems[i];
  487. if (self.pickerOptions.pickedAssetModels.count < self.pickerOptions.maxAssetsCount) {
  488. model.picked = YES;
  489. model.number = (int)self.pickerOptions.pickedAssetModels.count + 1;
  490. [self.pickerOptions.pickedAssetModels addObject:model];
  491. }else{
  492. model.picked = NO;
  493. model.number = 0;
  494. }
  495. [currentAlbum.assetArray insertObject:model atIndex:1];
  496. [indexPaths addObject:[NSIndexPath indexPathForItem:i+1 inSection:0]];
  497. }
  498. }
  499. [self.collectionView performBatchUpdates:^{
  500. NSArray<PHAsset *> *insertItems = changes.insertedObjects;
  501. if (insertItems && insertItems.count > 0) {
  502. [self.collectionView insertItemsAtIndexPaths:indexPaths];
  503. [changes enumerateMovesWithBlock:^(NSUInteger fromIndex, NSUInteger toIndex) {
  504. [self.collectionView moveItemAtIndexPath:[NSIndexPath indexPathForItem:fromIndex inSection:0] toIndexPath:[NSIndexPath indexPathForItem:toIndex inSection:0]];
  505. }];
  506. [self.collectionView reloadItemsAtIndexPaths:indexPaths];
  507. }
  508. } completion:^(BOOL finished) {
  509. [self resetAlbums];
  510. }];
  511. }
  512. }
  513. }
  514. });
  515. }
  516. #pragma mark - UIImagePickerControllerDelegate
  517. - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
  518. NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
  519. if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {
  520. UIImage *image = info[UIImagePickerControllerOriginalImage];
  521. UIImageWriteToSavedPhotosAlbum(image, self, @selector(image: didFinishSavingWithError: contextInfo:), nil);
  522. }else{
  523. NSURL *url = [info objectForKey:UIImagePickerControllerMediaURL];
  524. NSString *urlStr = [url path];
  525. if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(urlStr)) {
  526. UISaveVideoAtPathToSavedPhotosAlbum(urlStr, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
  527. }
  528. }
  529. if (self.currentAlbumIndexpath.row != 0) {
  530. [self switchToCameraRoll];
  531. }
  532. [picker dismissViewControllerAnimated:YES completion:nil];
  533. }
  534. - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
  535. [picker dismissViewControllerAnimated:YES completion:nil];
  536. }
  537. - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
  538. }
  539. - (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
  540. }
  541. @end
  542. @implementation NavTitleView
  543. #pragma mark 懒加载
  544. -(UIButton *)titleBtn{
  545. if (_titleBtn == nil) {
  546. _titleBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  547. self.titleBtn.titleLabel.font = kTitleViewTitleFont;
  548. [self.titleBtn setTitleColor:COLOR_LABEL forState:UIControlStateNormal];
  549. _titleBtn.widthHeight = XY(W(100),W(40));
  550. }
  551. return _titleBtn;
  552. }
  553. - (UIImageView *)arrowView{
  554. if (_arrowView == nil) {
  555. _arrowView = [UIImageView new];
  556. _arrowView.image = [UIImage imageNamed:@"down-black"];
  557. _arrowView.widthHeight = XY(W(12),W(7));
  558. }
  559. return _arrowView;
  560. }
  561. -(XG_BarButton *)leftBarButton{
  562. if (_leftBarButton == nil) {
  563. XG_BarButtonConfiguration *config = [[XG_BarButtonConfiguration alloc]init];
  564. config.type = XG_BarButtonTypeImage;
  565. config.normalImageName = @"cancel-deep";
  566. _leftBarButton = [[XG_BarButton alloc]initWithConfiguration:config];
  567. [_leftBarButton addTarget:self action:@selector(onLeftBarButtonClick) forControlEvents:UIControlEventTouchUpInside];
  568. _leftBarButton.widthHeight = XY(W(40),W(40));
  569. }
  570. return _leftBarButton;
  571. }
  572. -(UIButton *)rightBarButton{
  573. if (_rightBarButton == nil) {
  574. XG_BarButtonConfiguration *config = [[XG_BarButtonConfiguration alloc]init];
  575. config.type = XG_BarButtonTypeText;
  576. config.titleString = @"下一步";
  577. config.normalColor = kAppThemeColor;
  578. config.disabledColor = [UIColor lightGrayColor];
  579. config.titleFont = [UIFont boldSystemFontOfSize:15];
  580. _rightBarButton = [[XG_BarButton alloc]initWithConfiguration:config];
  581. [_rightBarButton addTarget:self action:@selector(onConfirmBtnClick) forControlEvents:UIControlEventTouchUpInside];
  582. _rightBarButton.widthHeight = XY(W(75),W(28));
  583. // _rightBarButton.backgroundColor = COLOR_BLUE;
  584. [GlobalMethod setRoundView:_rightBarButton color:[UIColor clearColor] numRound:20 width:0];
  585. }
  586. return _rightBarButton;
  587. }
  588. #pragma mark 初始化
  589. - (instancetype)initWithFrame:(CGRect)frame{
  590. self = [super initWithFrame:frame];
  591. if (self) {
  592. self.backgroundColor = [UIColor whiteColor];
  593. self.width = SCREEN_WIDTH;
  594. [self addSubView];
  595. }
  596. return self;
  597. }
  598. //添加subview
  599. - (void)addSubView{
  600. [self addSubview:self.titleBtn];
  601. [self addSubview:self.arrowView];
  602. [self addSubview:self.leftBarButton];
  603. [self addSubview:self.rightBarButton];
  604. //初始化页面
  605. [self resetViewWithStr:nil];
  606. }
  607. #pragma mark 刷新view
  608. - (void)resetViewWithStr:(NSString *)str{
  609. [self removeSubViewWithTag:TAG_LINE];//移除线
  610. //刷新view
  611. [_titleBtn setTitle:UnPackStr(str) forState:(UIControlStateNormal)];
  612. self.titleBtn.centerXCenterY = XY(SCREEN_WIDTH/2,self.height/2);
  613. self.arrowView.leftCenterY = XY(self.titleBtn.right+W(10),self.titleBtn.centerY);
  614. self.leftBarButton.leftCenterY = XY(W(10),self.titleBtn.centerY);
  615. self.rightBarButton.rightCenterY = XY(SCREEN_WIDTH-W(10),self.titleBtn.centerY);
  616. self.height = NAVIGATIONBAR_HEIGHT-STATUSBAR_HEIGHT;
  617. }
  618. - (void)onLeftBarButtonClick{
  619. if (self.blockLeft) {
  620. self.blockLeft();
  621. }
  622. }
  623. - (void)onConfirmBtnClick{
  624. if (self.blockRight) {
  625. self.blockRight();
  626. }
  627. }
  628. @end
  629. @implementation XG_AssetPickerOptions
  630. -(NSMutableArray<XG_AssetModel *> *)pickedAssetModels{
  631. if(_pickedAssetModels == nil) _pickedAssetModels = [NSMutableArray array];
  632. return _pickedAssetModels;
  633. }
  634. @end