仿微信圖片多選模塊封裝(支持縮放、分組列表選擇、設置圖片上限)

封裝的效果到底好不好,先來看看效果圖。自我感覺良好,同微信圖片多選模塊項目不會差到哪里,只是暫時沒有選擇原圖功能,demo中默認選擇高清圖像。這個功能實現起來也比較簡單,只要更改圖片尺寸無論是高清圖像還是縮略圖都可以輕松獲取,后面代碼分析中會說明。由于實際開發中,項目需求很少用到是否選擇原圖這一模塊,所以綜合考慮就沒有增添這一模塊。Demo下載地址:https://github.com/ZhengYaWei1992/ZWChooseMultiImages

效果圖

首先看一下外部調用實現代碼。

 ZWPhotoGroupsViewController *groupsVC = [[ZWPhotoGroupsViewController alloc]init];
    UINavigationController *groupsNav = [[UINavigationController alloc]initWithRootViewController:groupsVC];
    [[ZWImageHelper shareImageHelper]getAllImageActionWithCollection:nil];
    [self presentViewController:groupsNav animated:YES completion:nil];

選中的照片資源主要是放在[ZWImageHelper shareImageHelper].phassetChoosedArr里面。

 [self.chooseImages addObjectsFromArray:[ZWImageHelper shareImageHelper].phassetChoosedArr];

先說一下整體架構吧。主要分為四個模塊,分別見Demo中的ZWChooseMultiImages文件夾下的相關文件,PhotosList主要負責展示特定分組下的所有照片,PhotosGroups主要負責顯示所有照片分組,FullImage主要負責顯示預覽照片(支持縮放手勢),ZWImageHelper主要是通過單例的形式保存特定分組下的照片以及選中的照片。PHAsset+addFlag主要是為PHAsset擴展chooseFlag屬性,記錄照片是否是被選中的資源。ZWChooseMultiImagesConfig是一個配置文件,這里面可以更改界面相關樣式,如字體顏色和大小、上下view的背景顏色、以及可以選擇最多圖片數量的上限。

關于獲取如何獲取系統的照片資源。獲取系統的圖片資源主要是使用<Photos/Photos.h>這個框架文件。獲取特定分組里面的所有資源圖片。

//獲取一個相冊里面所有照片的操作
- (void)getAllImageActionWithCollection:(PHFetchResult *)result {
    if (result) {
        for (id obj in result) {//獲取標識符
            [self.phassetArr addObject:obj];
        }
    }else {
        // 獲取所有資源的集合,并按資源的創建時間排序
        ///獲取資源時的參數
        PHFetchOptions *options = [[PHFetchOptions alloc] init];
        options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
        //表示一系列的資源的集合,也可以是相冊的集合
        PHFetchResult *assetsFetchResults = [PHAsset fetchAssetsWithOptions:options];
        for (id obj in assetsFetchResults) {//獲取標識符
            
            [self.phassetArr addObject:obj];
        //============================================
        //重點說明:如果不采用標志符方式,而是按照如下方式,讀取太慢會導致拖動卡頓
        //            PHAsset *asset = obj;
        //            if ([asset.localIdentifier isKindOfClass:[NSString class]]) {
        //                [self.phassetArr addObject:asset.localIdentifier];
        //            }
        }
      
    }
}

獲取所有包含照片資源的分組列表。

- (void)getAllKindImagesAction {
    PHFetchResult *kindAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    for (PHAssetCollection *colllection  in kindAlbum) {
        NSString *kindName = colllection.localizedTitle;
        PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:colllection options:nil];
        NSString *imageCount = [@(result.count) stringValue];
        NSDictionary *resultDic = @{@"count" : imageCount, @"title" : kindName, @"result" : result};
        //過濾掉照片個數為0的分組
        NSString *countStr = resultDic[@"count"];
        if (![countStr isEqualToString:@"0"]) {
            [self.kindArr addObject:resultDic];
        }
    }
}

從選中的圖片數組中讀取單張圖片信息。

- (void)getAllKindImagesAction {
    PHFetchResult *kindAlbum = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    for (PHAssetCollection *colllection  in kindAlbum) {
        NSString *kindName = colllection.localizedTitle;
        PHFetchResult *result = [PHAsset fetchAssetsInAssetCollection:colllection options:nil];
        NSString *imageCount = [@(result.count) stringValue];
        NSDictionary *resultDic = @{@"count" : imageCount, @"title" : kindName, @"result" : result};
        //過濾掉照片個數為0的分組
        NSString *countStr = resultDic[@"count"];
        if (![countStr isEqualToString:@"0"]) {
            [self.kindArr addObject:resultDic];
        }
    }
}

從選中的圖片資源中讀取單張圖片信息,并任意設置圖片大小。

/*
相關說明:asset,圖像對應的 PHAsset。
 targetSize,需要獲取的圖像的尺寸,如果輸入的尺寸大于資源原圖的尺寸,則只返回原圖。需要注意在 PHImageManager 中,所有的尺寸都是用 Pixel 作為單位(Note that all sizes are in pixels),因此這里想要獲得正確大小的圖像,需要把輸入的尺寸轉換為 Pixel。如果需要返回原圖尺寸,可以傳入 PhotoKit 中預先定義好的常量?PHImageManagerMaximumSize,表示返回可選范圍內的最大的尺寸,即原圖尺寸。
 contentMode,圖像的剪裁方式,與?UIView 的 contentMode 參數相似,控制照片應該以按比例縮放還是按比例填充的方式放到最終展示的容器內。注意如果 targetSize 傳入?PHImageManagerMaximumSize,則 contentMode 無論傳入什么值都會被視為?PHImageContentModeDefault。
 options,一個?PHImageRequestOptions 的實例,可以控制的內容相當豐富,包括圖像的質量、版本,也會有參數控制圖像的剪裁,下面再展開說明。
 resultHandler,請求結束后被調用的 block,返回一個包含資源對于圖像的 UIImage 和包含圖像信息的一個 NSDictionary,在整個請求的周期中,這個 block 可能會被多次調用,關于這點連同 options 參數在下面展開說明。
*/
- (void)displayCellWithAssetString:(PHAsset *)asset  {
    __weak ZWChoosedCollectionViewCell *weakSelf = self;
    
    
    PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
    options.synchronous = YES;
    options.resizeMode = PHImageRequestOptionsResizeModeFast;
    
    //小圖,大小自己定義
//    CGSize imageSize = CGSizeMake(CELL_COLLECTION_WIDTH - 6, CELL_COLLECTION_WIDTH - 6);
//    [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
//        weakSelf.chooseImage.image = result;
//    }];
    
    //高清圖
    [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:PHImageManagerMaximumSize contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
        weakSelf.chooseImage.image = result;
    }];
}

另外有一點非常值得說明的是關于界面跳轉問題,因為第一次進入圖片瀏覽器會發現并不是直接就跳轉到照片分組列表界面,而是跳轉到特定分組下的某個分組內的圖片選擇界面。這種跳轉方式可能有n種解決方案,但是感覺微信的這種跳轉更為合理(模態進入照片選擇模塊,模態離開照片選擇界面)。見過其他的照片多選第三方框架,但是感覺很多在這一塊做得都不是很好。這個demo中,照片多選模塊的進入和離開方式和微信上是一樣的。其實很簡單的,只要在展示照片分組的viewDidLoad方法中多加上一句代碼即可,剩下的就是常規的模態進入和離開。

//首次進入直接跳轉到下一界面
   [self.navigationController pushViewController:self.listVC animated:NO];

天機了這句代碼之后,就能保證首次進入照片多選模塊后,直接進入第二界面。但是要格外注意animated參數設置為NO,否則實際運行過程中會顯示第一個界面。

因為這個照片多選模塊的封裝代碼量還是不少的,就簡單說著幾個重點吧,其余的都相對而言比較簡單。具體可以參照我github上的demo。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,841評論 25 708
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,180評論 4 61
  • 城市與農村有的不只是距離
    順勢而上閱讀 192評論 0 0
  • 之所以有這個題目是因為我在支付寶的刮刮樂里刮到了一個什么彩票,然后心心念念等著開獎,終于午睡時如愿以償夢到自己中獎...
    米線兒_2017閱讀 236評論 4 2
  • 姓名: 張娟 公司: 路易彬彥 【日精進打卡第119天】 【知~學習】 《六項精進》1遍共137遍 《大學》0遍 ...
    路易彬彥張娟閱讀 230評論 0 0