前言
应用场景:上传和展示多张图片的场景,比如风险商户处理、发布商品图片
效果图:
技术特点:使用UICollectionViewCell、UITableViewCell 控件进行搭建,使用Masonry 框架布局,采用MVVM结构。
我的其他相关SDK pod 'KNPodlib'
核心处理逻辑及注意事项【上篇】
https://kunnan.blog.csdn.net/article/details/121550416
demo下载地址请搜索微信小程序:iOS逆向,进入发现页搜索“上传图片视图”。
I、 用法
配置相册访问权限key
NSPhotoLibraryUsageDescription
The app's Info.plist must contain an NSPhotoLibraryUsageDescription key with a string value explaining to the user how the app uses this data.
1.1 初始化 cell
- cell
case ERPRelease_commoditiesViewSection4UploadPic:{ return [ERPcomposePhotosTableViewCell tableViewCellWithTableView:tableView block:^(id _Nonnull sender) { } models:self.viewModel.Model4UploadPictures]; }break;
- 上传图片界面的初始模型数据
#pragma mark - ******** 上传图片界面的初始模型数据 + (NSMutableArray*)getModel4ADDUploadPicturesWithBlock:(void (^)(id sender))block { NSMutableArray *tmpD = @[ @{@"block":block,@"imgName":@"img_zhuece_tianjia",@"imageType":[NSNumber numberWithInt:ERPimageType4name],@"type":[NSNumber numberWithInt:QCTCollectionModelType4UploadPicturesAddIcon],@"isHiddenDelBtn":@1}, ]; NSMutableArray *tmp = [[self class] mj_objectArrayWithKeyValuesArray:tmpD]; return tmp; }
- 处理上传图片逻辑
- (void)Model4UploadPictures{ __weak __typeof__(self) weakSelf = self; self.viewModel.Model4UploadPictures = [QCTCollectionModel getModel4ADDUploadPicturesWithBlock:^(UISwitch* sender) { [weakSelf setupChooseimage];//上传图片 } ]; }
1.2 初始化 cellView
ERPcomposePhotosV4UploadPictures
- (ERPcomposePhotosV4UploadPictures *)cellView{ if (nil == _cellView) { ERPcomposePhotosV4UploadPictures *tmpView = [[ERPcomposePhotosV4UploadPictures alloc]init]; _cellView = tmpView; [tmpView setBackgroundColor:kcellColor]; [self.contentView addSubview:tmpView]; __weak __typeof__(self) weakSelf = self; [tmpView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.equalTo(weakSelf.contentView).offset(kAdjustRatio(20)); make.right.equalTo(weakSelf.contentView).offset(- kAdjustRatio(20)); make.top.equalTo(weakSelf.contentView).offset(kAdjustRatio(0)); make.bottom.equalTo(weakSelf.contentView).offset(- kAdjustRatio(0)); }]; } return _cellView; }
1.3 约束的设置
根据模型数据,更新视图高度
mas_updateConstraints 计算宽度的时候采用UIScreen进行屏幕宽度的获取
- (void)setModels:( NSMutableArray*)models{ _models =models; self.cellView.models = models; NSInteger maxclos= 3;// 列数 CGFloat margin = 10; // // [self.cellView layoutIfNeeded]; // CGFloat w = (self.cellView.frame.size.width - margin*(maxclos-1))/maxclos; CGFloat cellViewW =kWidth-kAdjustRatio(20*2) ;//计算宽度的时候采用UIScreen进行屏幕宽度的获取 CGFloat w = (cellViewW- margin*(maxclos-1))/maxclos; CGFloat cell_H = w*(1);//宽高比 // NSLog(@"cell_H:%f",cell_H);// NSInteger row = [QCT_Common getRowWithCount:models.count clos:maxclos]; [self.cellView mas_updateConstraints:^(MASConstraintMaker *make) { make.height.mas_equalTo(kAdjustRatio(cell_H*row + (row -1)*10 )); }]; }
设置sizeForItemAtIndexPath
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { CGSize size; NSInteger maxclos= 3;// 列数 CGFloat margin = 10; CGFloat w = (self.frame.size.width - margin*(maxclos-1))/maxclos; CGFloat cell_H = w*(1);//宽高比 123/234 size = CGSizeMake(cell_H, cell_H); return size; }
初始化collectionView,并设置每一行之间的间距
- (UICollectionView *)collectionView { if (_collectionView == nil) { UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init]; // 2.设置整个collectionView的内边距 //分别为上、左、下、右 flowLayout.sectionInset = UIEdgeInsetsMake(kAdjustRatio(0),kAdjustRatio(0),kAdjustRatio(0),kAdjustRatio(0)); //.设置每一行之间的间距 flowLayout.minimumLineSpacing = kAdjustRatio(10); flowLayout.minimumInteritemSpacing = 0; // flowLayout.itemSize = CGSizeMake((SCREEN_WIDTH-3*kAdjustRatio(10))/3.0, self.optionsView.height); _collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:flowLayout]; _collectionView.backgroundColor = [UIColor whiteColor]; _collectionView.showsVerticalScrollIndicator = NO; _collectionView.bounces = NO; _collectionView.dataSource = self; _collectionView.delegate = self; [_collectionView registerClass:[ERPUploadPicturesUICollectionViewCell class] forCellWithReuseIdentifier:@"ERPUploadPicturesUICollectionViewCell"]; if (@available(iOS 11.0, *)) { _collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; } else { // Fallback on earlier versions } _collectionView.scrollEnabled = NO; // UICollectionViewScrollDirectionHorizontal __weak __typeof__(self) weakSelf = self; [self addSubview:_collectionView]; [_collectionView mas_makeConstraints:^(MASConstraintMaker *make) { make.left.top.bottom.right.equalTo(weakSelf); }]; } return _collectionView; }
1.4 处理图片添加成功的用法举例
- (void)UpdateImageToViewWithurl:(NSString*)picurl{ __weak __typeof__(self) weakSelf = self; // 新增模型 QCTCollectionModel *tm = [QCTCollectionModel new]; tm.type = QCTCollectionModelType4ShowUploadPictures; tm.imageType = ERPimageType4url; tm.picurl = picurl; [tm setDelblock:^(QCTCollectionModel* sender) { [weakSelf.viewModel.Model4UploadPictures removeObject:sender]; //判断是否已经包含添加图片视图,如果没有,且数量小于上传的最大张数,则显示添加按钮 if(self.viewModel.Model4UploadPictures.count<maxcount4UploadPicturesInRelease_commodities && ( ![QCTCollectionModel idContainsUploadPicturesAddIconWithArr:self.viewModel.Model4UploadPictures])){// 处理最大数量 [weakSelf.viewModel.Model4UploadPictures addObject:[QCTCollectionModel getModel4ADDUploadPicturesWithBlock:^(UISwitch* sender) { [weakSelf setupChooseimage]; } ].firstObject]; } [weakSelf.viewModel.reloadProductFileUploadSubject sendNext:nil]; }]; [tm setBlock:^(id _Nonnull sender) { }]; [self.viewModel.Model4UploadPictures insertObject:tm atIndex:self.viewModel.Model4UploadPictures.count-1]; if(self.viewModel.Model4UploadPictures.count>maxcount4UploadPicturesInRelease_commodities){// 处理最大数量 [self.viewModel.Model4UploadPictures removeLastObject]; } // 刷新视图 [self.viewModel.reloadProductFileUploadSubject sendNext:nil]; }