CBImagePicker:原始碼分析

Super邦發表於2016-08-11

本開源庫基於iOS8中PhotoKit框架製作,所以暫不支援iOS8以下版本,請諒解。另,在iOS10中,使用photoKit框架的應用可能會出現crash,但這個問題相信很快會被官方修復,請無需擔心。

效果圖

CBImagePicker:原始碼分析

實際截圖

CBImagePicker:原始碼分析

以下是原Idea作者的Dribble:Photo Picker Interaction 地址和本人的GitHub:CBImagePicker地址,希望大家點選支援,再次感謝。

下面我們來仔細的分析,做這個庫的完整過程。

第一部分 Category

整個庫的製作用到了大量的座標計算,所以我們很有必要寫一個category來簡化這一部分操作,我針對UIViewUIView+CBAddition類庫和針對UIImageUIImage+CBAddition都是為了簡化這一部分內容而做的工作。

大都以設定屬性後自定義Getter和Setter的方式來進行,更詳細程式碼請點選檢視。

第二部分 ImagePicker(圖片選擇)

這個部分我們分小節來講。

CBImagePicker:原始碼分析

TitleView

TitleView分為兩個View,第一個是Label,第二個則是UIImageView,這裡使用了蘋果原生NSLayoutConstraint來新增約束去限制兩個View之間的位置和尺寸的關係,使用方法如下:

引數說明:

view1:設定的目標檢視 attr1:設定的目標檢視的屬性 relation:目的檢視和參照檢視之間的關係view2:設定的參照檢視 attr2:參照檢視的參照屬性 multiplier:目標檢視屬性和參照檢視屬性倍值 c:目標檢視屬性和參照檢視屬性差異值

CollctionView

CBImagePicker:原始碼分析

相簿獲取

collection這個部分,主要是圖片資料的申請,這裡首先使用了PhotoKit來申請所有的相簿列表,程式碼如下:

這裡使用了一個陣列儲存所取到的所有相簿列表,相簿資訊儲存物件為PHAssetCollection

相簿圖片獲取

而當我們取到相簿資訊之後,要從對應相簿中取到我們所需要顯示的圖片,那麼這裡我們根據index從上面的陣列中取出我們所需要的對應相簿,遍歷改相簿,再利用方法requestImageForAsset來請求圖片資訊,方法如下:

引數說明:
asset:單個的圖片資料 targetSize:請求的圖片尺寸 cotentMode:尺寸拉伸方式 options:附加資訊resultHandler:結果回撥

此處自定義了一個頭部檢視,新增方法如下:

註冊registerClass

設定dataSource

當進行圖片選擇時,頭部檢視會向下滑動,而當開始取消選擇圖片,且選擇圖片為空時,頭部檢視向上滑動,這一部分操作,我使用了UIView動畫來製作,方法內容如下:

引數說明:

duration:持續時間 delay:延時時間 dampingRatio:spring係數,從0-1,數值越小,效果越強velocity:初始速度 options:動畫選項 animations:動畫block completion:動畫結束後的回撥

animations block中設定了collectionVieworiginUpsizeHeightcontentOffset,作為最終狀態,而上面那個方法則會自動完成中間狀態的計算和設定。

CollectionViewCell

CBImagePicker:原始碼分析

在cell裡面,同樣使用了約束和UIView動畫,在動畫中使用了View的transform屬性,點選時設定cell的transform為CGAffineTransformMakeScale(0.9, 0.9),即縮小狀態,取消點選時設定cell的transform為CGAffineTransformMakeScale(1, 1),即正常大小,形成一種強烈的選中效果。

AlbumTableView

CBImagePicker:原始碼分析

這裡自定義了一個下拉選單,整個下拉選單的製作並沒有困難的地方,同樣使用了UIView動畫來進行frame上的位移設定。使用了requestImageForAsset:的方法進行縮圖請求。

第三部分 ImageBrowser(圖片瀏覽)

Simulator Screen Shot 2016年8月7日 下午5.08.56.png

動畫顯示

這個瀏覽器,我寫了這樣的一個present的方法。我們從這個方法入手。

引數設定:

fromView:通過該View的絕對位置,我們取到初始變化的Bounds toContainer:瀏覽器所add上去的檢視 animated:動畫選擇 completion完成回撥

下面的兩個動畫方法,分別用來做瀏覽器的顯示和隱藏動效,結合fromView的bounds值,可以做到檢視從所點選處的View變化而來的效果。點選檢視更多程式碼。

顯示動畫:

隱藏動畫:

第一層ScrollView

Simulator Screen Shot 2016年8月7日 下午5.10.35.png

這個瀏覽器使用了兩層的ScrollView,第一層是用來盛放第二層的ScrollView,起到了滑動選擇不同圖片的效果,第一層的ScrollView的contentSize通過所傳入的圖片陣列動態改變。

第二層ScrollView

第二層的ScrollView起到了作為類似cell的作用,我們簡單的通過官方的一個方法:

傳入一個ImageView即可自動完成二指縮放的效果,非常方便。但我們還是需要自己處理單擊,雙擊,長按和雙擊事件,下面我們來看這一部分內容。

單擊,雙擊,長按和雙擊手勢的處理

我們先依次新增手勢,記得要新增[singleTap requireGestureRecognizerToFail:doubleTap];保證雙擊手勢和單擊手勢之間的手勢衝突得到解決。

單擊手勢我們直接使用block來執行dismiss方法即可,這裡不表。雙擊手勢呢,我們用下面的方法來進行縮放,主要是計算rect和scale。

長按手勢我是直接呼叫系統的popoverPresentationController:方法,可以實現分享和儲存等功能。

Pan手勢相對複雜,利用velocityInView:來取得滑動速度,利用locationInView:來取得滑動的初始位置和最終位置。主要的處理邏輯是進行初始位置和最終位置進行對比,如果數值較大,就執行動畫並進行dismiss,而如果數值較小就取消滑動,恢復初始位置。而一旦初始速度很大的時候,就直接執行動畫並dismiss,判斷使用者的行為,並作出操作。
這一部分內容較多,請直接點選檢視

第四部分 總結

這個庫的製作過程基本如上所述,但仍有很多細節難以細講,請諒解,請有意向的朋友下載demo檢視,如有疑問或者BUG,歡迎留言或者提出issue,謝謝。

相關文章