从相册多选照片更新界面的collectionView

作者: NateLam | 来源:发表于2016-09-06 15:30 被阅读330次

此次我用的是三方QBImagePickerController, CTAssetsPickerController也可以, 他们之间的区别暂时我觉得是多选照片时, 前者是对钩√, 后者是排序号1234.., 个人觉得对钩似乎比较好看点就用了前者

注意, 如果要避免进入过一次相册后再进入, 让相册忘记之前选过的图片, 则不能对imagePicker使用懒加载, 每次进入相册都应是new一个新的picker

从图库回来后, 市面上的app基本都是以collectionView呈现多选后的图片, 如果未满最大可选照片数, 最后一个item会覆盖一个加号图片, 以示可以继续添加新的图片

所以创建collectionView就不写了

首先使用cocoaPods导入

pod 'CTAssetsPickerController',  '~> 3.3.0'

或者

pod 'QBImagePickerController', '~> 3.4.0'

本次就只写后者

然后引入头文件

#import <QBImagePickerController/QBImagePickerController.h>

然后签协议, 第三个不用说, 后两个是为了可以使用拍照功能

@interface QBViewController ()<UICollectionViewDelegate, UICollectionViewDataSource, QBImagePickerControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>

属性

@property (nonatomic, strong) NACollectionView *collectionView;
@property (nonatomic, strong) NAFlowLayout *flowLayout;
@property (nonatomic, strong) NSMutableArray *mArrOfPics;//存储UIImage的数组
@property (nonatomic, strong) QBImagePickerController *imagePickerController;//多选的PickerController
@property (nonatomic, strong) UIImagePickerController *imagePicker;//拍照的PickerController
@property (nonatomic, assign) NSInteger numOfPicCanBeChoosed;//监听距离最大限制数量还有多少张可被选中

如果想自定义相册的navigationBar, 我暂时没什么好办法, 就是点进去QBImagePickerController, 修改init方法中的setUpAlbumsViewController方法, 添加以下三行

//以下这三行我写的
navigationController.navigationBar.barTintColor = [UIColor colorWithRed:0 green:148 / 255.f blue:1 alpha:1];
//按钮字体颜色
navigationController.navigationBar.tintColor = [UIColor whiteColor];
//title字体大小和颜色
[[UINavigationBar appearance] setTitleTextAttributes:@{
                                                NSForegroundColorAttributeName:[UIColor whiteColor],
                                                       NSFontAttributeName:[UIFont systemFontOfSize:16 * [UIScreen mainScreen].bounds.size.width / 375]
                                                       }];

一开始先把该初始化的初始化, 我设置最多可选6张照片

- (void)viewDidLoad{
    [super viewDidLoad];

    _numOfPicCanBeChoosed = 6;
    _mArrOfPics = [NSMutableArray array];
    [self createCollectionView];
}

推出相机的imagePicker还是可以懒加载的

- (UIImagePickerController *)imagePicker{
    if (!_imagePicker) {
        _imagePicker = [[UIImagePickerController alloc] init];
        _imagePicker.delegate = self;
    
        //模态推出照相机页面的样式
        _imagePicker.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
//        _imagePicker.allowsEditing = YES;
        self.imagePicker.sourceType =   UIImagePickerControllerSourceTypeCamera;
    }
    return _imagePicker;
}

#pragma mark - 注销
- (void)dealloc{

    self.imagePickerController.delegate = nil;
    self.imagePicker.delegate = nil;
}

以下是collectionView三个协议方法, cell上面就是imageView和左上角的删除button, 当没选任何图片或者六张照片全满时, 删除按钮隐藏

#pragma mark - item个数
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{

    if (_mArrOfPics.count == 0) {
        return 1;
    }else if(_mArrOfPics.count > 0 && _mArrOfPics.count < 6){
        return _mArrOfPics.count + 1;
    }
    else if(_mArrOfPics.count == 6){
        return 6;
    }
    else{
        return 0;
    }
}

#pragma mark - 取出cell
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    NACollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NACollectionViewCell" forIndexPath:indexPath];

    NSLog(@"!!!%ld", _mArrOfPics.count);

    //添加了照片
    if (_mArrOfPics.count > 0) {
        cell.buttonOfDelete.hidden = NO;
        for (NSInteger i = 0; i < _mArrOfPics.count; i++) {
            UIImage *image = _mArrOfPics[i];
            if (indexPath.row == i) {
            
                cell.buttonOfDelete.tag = indexPath.row;
                cell.imageViewOfPic.image = image;
            }
            if (indexPath.row == _mArrOfPics.count) {
                cell.imageViewOfPic.image = [UIImage imageNamed:@"add"];
                cell.buttonOfDelete.hidden = YES;
            }
        }
    }

    //没有添加照片时
    else{
        cell.buttonOfDelete.hidden = YES;
        cell.imageViewOfPic.image = [UIImage imageNamed:@"add"];
    }

    cell.deletePics = ^(UIButton *button){
    
        if (indexPath.row == button.tag) {
            [_mArrOfPics removeObjectAtIndex:indexPath.row];
            _numOfPicCanBeChoosed = 6 - _mArrOfPics.count;
            [_collectionView reloadData];
        }
    };

    return cell;
}

#pragma mark - 点击item
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{

    if(_mArrOfPics.count < 6){
    
        if (indexPath.row == _mArrOfPics.count) {
        
            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle: UIAlertControllerStyleActionSheet];
            UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
            UIAlertAction *takePicAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
                [self selectImageFromCamera];
            }];
            UIAlertAction *albumAction = [UIAlertAction actionWithTitle:@"从手机相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            
                [self choosePicFromAlbum];
            }];
            [alertController addAction:cancelAction];
            [alertController addAction:takePicAction];
            [alertController addAction:albumAction];
            [self presentViewController:alertController animated:YES completion:nil];
        }
    }
}

选择去相册则对应以下方法

#pragma mark - 从相册选
- (void)choosePicFromAlbum{
    //这样就可以让navi顶部与app风格一致
    //    UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:self.imagePickerController];

    _imagePickerController = [[QBImagePickerController alloc] init];
    //默认是any
    _imagePickerController.mediaType = QBImagePickerMediaTypeImage;
    _imagePickerController.assetCollectionSubtypes = @[
                                                   @(PHAssetCollectionSubtypeSmartAlbumUserLibrary), // Camera Roll
                                                   @(PHAssetCollectionSubtypeAlbumMyPhotoStream), // My Photo Stream
                                                   @(PHAssetCollectionSubtypeSmartAlbumPanoramas), // Panoramas
                                                   @(PHAssetCollectionSubtypeSmartAlbumVideos), // Videos
                                                   @(PHAssetCollectionSubtypeSmartAlbumBursts) // Bursts
                                                   ];

    //        _imagePickerController.prompt = @"选择照片";
    _imagePickerController.showsNumberOfSelectedAssets = YES;
    _imagePickerController.delegate = self;
    _imagePickerController.allowsMultipleSelection = YES;
    _imagePickerController.maximumNumberOfSelection = 6;

    //默认相册显示的预选照片尺寸
    _imagePickerController.numberOfColumnsInPortrait = 4;
    _imagePickerController.numberOfColumnsInLandscape = 7;

    [self presentViewController:self.imagePickerController animated:YES completion:nil];
}

进入相册就连带着调用了一些协议方法, 我选了两个需要用到的时机, 选完后和将要选择某张图片时, 后者是为了阻止超出图片最大限制数量

进入选完图片这个协议方法, 网上很多前辈进行数组初始化, 不, 万一这位用户只想在前面选择基础上继续添加图片呢

#pragma mark - 选完照片
- (void)qb_imagePickerController:(QBImagePickerController *)imagePickerController didFinishPickingAssets:(NSArray *)assets   {

//    _mArrOfPics = [NSMutableArray array];

    // 基本配置
    CGFloat scale = [UIScreen mainScreen].scale;
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.resizeMode   = PHImageRequestOptionsResizeModeNone;
    options.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;

    for (PHAsset *asset in assets) {
        CGSize size = CGSizeMake(asset.pixelWidth / scale, asset.pixelHeight / scale);
        // 获取图片
        [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        
            [_mArrOfPics addObject:result];
            self.numOfPicCanBeChoosed = 6 - _mArrOfPics.count;
            [_collectionView reloadData];
        }];
    }

    // 关闭图片选择界面
    [self dismissViewControllerAnimated:YES completion:nil];
}

接下来是将要选择图片时

#pragma mark - 要选中某张图片之前
- (BOOL)qb_imagePickerController:(QBImagePickerController *)imagePickerController shouldSelectAsset:(PHAsset *)asset{

    if(self.imagePickerController.selectedAssets.count + 1 <= self.numOfPicCanBeChoosed){
        return YES;
    }else{
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"一次最多上传6张图片" preferredStyle:UIAlertControllerStyleAlert];
        [imagePickerController presentViewController:alert animated:YES completion:nil];
//让alert自动消失
        [NSTimer scheduledTimerWithTimeInterval:1.5 target:self selector:@selector(creatAlert:) userInfo:alert repeats:NO];
        return NO;
    }
}

#pragma mark - 让警告消失
- (void)creatAlert:(NSTimer *)timer{

    UIAlertController *alert = [timer userInfo];
    [alert dismissViewControllerAnimated:YES completion:nil];
    alert = nil;
}

至于推出相机那部分, 之前有写过, 再写一遍, 区别就是拍照后, 监听剩余可添加图片数的属性变量要更新

#pragma mark - 选择拍照
- (void)selectImageFromCamera{

    //判断相机是否可用
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    
        //判断是否开启相机权限
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
        //权限未开启
        if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied){
        
            UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"抱歉" message:@"您尚未开启相机权限" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"去开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
                //info plist中URL type中添加一个URL Schemes添加一个prefs值
                if([[UIApplication sharedApplication] canOpenURL:url]){
                    //跳转到隐私
                    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Privacy&path=CAMERA"]];
                }
            }];
            UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"不了" style:UIAlertActionStyleDefault handler:nil];
            [alertController addAction:actionOK];
            [alertController addAction:actionCancel];
            [self presentViewController:alertController animated:YES completion:nil];
        }
        //权限已开启
        else{
            [self presentViewController:self.imagePicker animated:YES completion:^{}];
        }
    }
    //适用于没有相机的设备
    else{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"抱歉" message:@"相机不可用" preferredStyle:UIAlertControllerStyleAlert];
        [self presentViewController:alertController animated:YES completion:nil];
#pragma mark - 让alert自动消失
        [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(creatAlert:) userInfo:alertController repeats:NO];
    }

}

协议方法, 获取拍照后的图片, 顺便刷新collectionView和监听剩余可选图片的属性

#pragma mark - ImagePicker delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{

    UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

    //这个本来是想用于拍照后编辑的, 发现并没有用
    //self.isFullScreen = NO;

    //用拍下来的照片赋值
    [_mArrOfPics addObject:image];
    [_collectionView reloadData];

    self.imagePickerController.maximumNumberOfSelection = 6 - _mArrOfPics.count;
    self.numOfPicCanBeChoosed = 6 - _mArrOfPics.count;

    //访问相册权限, ios9之后的api, 要引入<Photos/Photos.h>
    PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];

    //相册权限已开启
    if(status == PHAuthorizationStatusAuthorized){
        //存入本地相册
        UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}

    //未开启相册权限
    //PHAuthorizationStatusNotDetermined,
    //PHAuthorizationStatusRestricted
    //PHAuthorizationStatusDenied
    else{
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"您尚未开启相册权限" message:@"无法存入所拍的照片" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *actionOK = [UIAlertAction actionWithTitle:@"去开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            //info plist中URL type中添加一个URL Schemes添加一个prefs值
            if([[UIApplication sharedApplication] canOpenURL:url]){
                //跳转到隐私
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Privacy&path=PHOTOS"]];
            }
        }];
        UIAlertAction *actionCancel = [UIAlertAction actionWithTitle:@"不了" style:UIAlertActionStyleDefault handler:nil];
        [alertController addAction:actionOK];
        [alertController addAction:actionCancel];
        [self presentViewController:alertController animated:YES completion:nil];
    }
    [picker dismissViewControllerAnimated:YES completion:nil];
}

#pragma mark - 存储到系统相册结果回调
- (void)image:(UIImage*)image didFinishSavingWithError:  (NSError*)error contextInfo:(void*)contextInfo{
    if (error){
        NSLog(@"%@", error);
    }
    else{
        NSLog(@"保存成功");
    }
}

相关文章

网友评论

本文标题:从相册多选照片更新界面的collectionView

本文链接:https://www.haomeiwen.com/subject/ceudettx.html