android开发分享按照日期对系统图片进行分类,并且支持多个section滑动选中

先放上效果图设计思路先获取到按照时间分类的相册集合,再利用CollectionView来展示获取到的图片,然后通过pan手势识别触摸区域内的子Cell。判断子Cell是选中还是取消。下面是具体实现步骤#获取图片资源利用PHCollectionList,获取到一个时刻集合。通过指定它的subType从而获取到以天为单位的时刻集合momentList。然后在遍历这个momentList的集合,从而获取里面的PHAssetCollection资源集合。然后从PHAssetCollection资源集合中取


先放上效果图

按照日期对系统图片进行分类,并且支持多个section滑动选中

设计思路

先获取到按照时间分类的相册集合,再利用CollectionView来展示获取到的图片,然后通过pan手势识别触摸区域内的子Cell。判断子Cell是选中还是取消。下面是具体实现步骤
#获取图片资源
利用PHCollectionList,获取到一个时刻集合。通过指定它的subType从而获取到以天为单位的时刻集合momentList。然后在遍历这个momentList的集合,从而获取里面的PHAssetCollection资源集合。然后从PHAssetCollection资源集合中取出相应的资源文件PHAsset,得到每天的照片数量。

通过以上方法我们就可以得到一个二维数组 Array[日期][具体照片]。完整实现代码如下

 NSMutableArray* momentArray = [NSMutableArray array];          PHFetchOptions *momentOptions = [[PHFetchOptions alloc]init];     momentOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"startDate" ascending:NO]];       PHFetchResult* collectionList = [PHCollectionList  fetchCollectionListsWithType:PHCollectionListTypeMomentList subtype:PHCollectionListSubtypeMomentListCluster options:momentOptions];     [collectionList enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {                  //创建一个时刻存放数组         PHCollectionList* momentList = (PHCollectionList*) obj;         NSMutableArray* dayArray = [NSMutableArray array];                  //获取时刻里面的Asset集合         PHFetchResult<PHAssetCollection*>* result = [PHAssetCollection fetchMomentsInMomentList:momentList options:momentOptions];         [result enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {             PHAssetCollection* collection = (PHAssetCollection*) obj;             //设置筛选条件             PHFetchOptions *asstsOptions = [[PHFetchOptions alloc]init];             asstsOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];             //获取Asset集合里面的Asset             PHFetchResult<PHAsset*>* assetResult = [PHAsset fetchAssetsInAssetCollection:collection options:asstsOptions];                          //遍历获取Asset             [assetResult enumerateObjectsUsingBlock:^(PHAsset * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {                 [dayArray addObject:[AMPHAssetsModel modelWithPHAsset:obj]];             }];         }];         if (dayArray.count > 0) {             AMAlbumModel* album = [[AMAlbumModel alloc] init];             album.name = [NSDate stringFromDate:momentList.startDate withFormat:@"yyyy年MM月dd"];             album.assetsArray = dayArray;             [momentArray addObject:album];         }     }]; 

CollectionView实现节标题悬浮

数据导入

以一日为一个section,这日内的所有资源Asset为Cell。得到了一个多节的CollectionView。

为CollectionView添加sectioneHeader

与TableView不同的是,要实现UICollectionview的sectionHeader需要,现在UICollectionView里面注册一个UICollectionReusableView并且为它指定好复用标识

[collectionView registerClass:[UICollectionReusableView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView"]; 

注册好header标识之后需要,通过实现UICollectionViewDataSource协议。为sectionHeaderView添加上我们想要的内容

- (UICollectionReusableView *) collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 

这里要注意的是
如果没有在sectionHeaderView上使用全局的控件 则需要在通过标识获取到复用的sectionHeaderView之后需要对之前添加在上面的View进行删除

实现sectionHeader悬浮状态

与tableView不同的是,我们在成功设置好了sectionHeader之后,滚动时发现sectionHeaderView无法实现类似于tableView的悬浮效果,所以这里我们需要在collectionLayout里面将layout.sectionHeadersPinToVisibleBounds = YES

layout.sectionHeadersPinToVisibleBounds = YES; 

CollectionView实现滑动多行选中

原理分析

通过使用UIPanGestureRecognizer手势,来获取到滑动触摸点point,然后通过CollectionView的indexPathForItemAtPoint方法获取到具体触摸到那个cell,并获取到其indexPath。从而实现获取到滑动过程中所选中的cell,并改变其选中状态。
下面分为三步来处理触摸事件。

触摸开始

首先获取到触摸点的Cell,通过判断cell的选中状态来,决定这个滑动是选中cell,还是取消已经选中的cell。并且记录下该cell的indexPath,作为起点cell.实现代码

 if (pan.state == UIGestureRecognizerStateBegan) {                  if (!indexPath) {             _beginSelect = NO;         }         else {             _beginSelect = YES;         }                  if(_beginSelect){             model.selected = !mode.selected          }     } 

触摸事件进行中

记录下我们滑动过程中所经过的cell。由于滑动过程中所经过的point可能会在同一个cell当中所以我们先要进行。判重操作。经过去重操作后。我们需要将这些选中的cell。按照第一步中所获取的状态进行对比,如果滑动开始时是选中状态,而选中的cell确实未选中状态,则改变该cell的状态。如果是相同的则不与改变。
判断开始选中的indexPath和最后滑到的indexPath的大小。如果开始选中的是大于最后的,则代表从开始的cell向前滑动,如果开始大于结束的,则代表是向后滑动。
注意由于我们这里是多个section,不能单单通过indexPath.row 来判断开始的indexPath和结束的indexPath的大小。需要先将二维数组转化为一位数组进行判断。
下面是将二维的图片数组下标,转换为一维的下标和将一维的下标转化为二维图片数组的下标

//将indexPath里面的row和section 转化为递增的数据 - (NSInteger) orderIndexWithIndexPath:(NSIndexPath*) path{          NSInteger sectionConout = 0;     for (int i = 0; i < path.section; i++) {         AMAlbumModel* model = self.dataArray[i];         sectionConout += model.assetsArray.count;     }     return path.row + sectionConout; }  - (NSIndexPath*) indexPathWithIndex:(NSInteger) index {      NSInteger division = 0;     NSInteger res = index;     NSInteger count = 0; //    NSLog(@"index %ld",index);      for(int i = 0; i < self.dataArray.count;i++){  // 2 1 1 3         AMAlbumModel* model = self.dataArray[i];         count += model.assetsArray.count;         if (index >= count) {             //大于之前的和  则跳转到下一个section             division++;         }         else {  //小于等于之前的和 则算出之前的section有多少 在求出row  并且终止循环             NSInteger sum = count - model.assetsArray.count;             res = index - sum;             break;         }     }     NSIndexPath* path = [NSIndexPath indexPathForRow:res inSection:division]; //    NSLog(@"res %ld",res); //    NSLog(@"over");      return path; } 

结束滑动

重置之前滑动的状态。并且清空第一步第二步所使用的数组。

Demo地址

下载地址

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/896324.html

(0)
上一篇 2021年10月21日
下一篇 2021年10月21日

精彩推荐