今天博客中,咱們就來實現一下一些經常使用資訊類App中經常使用的分類選擇的控件的封裝。本篇博客中沒有使用到什麼新的技術點,若是非得說用到了什麼新的技術點的話,那麼勉強的說,用到了一些iOS9之後UICollectionView添加的一些新的特性。本篇博客所涉及的技術點主要有UICollectionView的Cell移動,手勢識別,控件封裝,閉包回調,面向接口編程,Swift中的泛型等等。這些技術點在以前的博客中也屢次使用到,只不過本篇博客使用這些技術點來完成咱們的具體需求。git
1、實例運行效果github
先入爲主,下方這個效果,就是本篇博客所涉及Demo的運行效果。固然下方的效果是一些資訊類App中選擇分類時,經常使用的部分。主要仍是對UICollectionView的使用。固然,下方效果的實現,網上也不乏相應的實例。雖然本篇博客的效果與其餘相似的效果相似,可是代碼設計以及結構實現時仍是有所區別的。下方效果的實現使用了iOS9之後的UICollectionView才支持的更新Cell的方法,稍後會詳細介紹到。固然,本篇博客咱們依然使用Swift3.0來實現的。編程
在以前的博客中,咱們系列的介紹了UICollectionView的各類回調,以及如何自定義CollectionView的佈局,並給出瞭如何使用CollectionView自定義瀑布流。關於以前的博客請移步於《UICollectionView詳解系列》。數組
咱們可使用Reveal來查看上述效果的層級關係。下方就是咱們使用Reveal來查看的效果。從下方的效果中咱們不難看出,該頁面的實現並不複雜。主要仍是對UICollectionView的使用。閉包
上面這個效果就是咱們今天博客中所實現的效果,而下方這兩個效果是咱們以前在聊UICollectionView以及自定義佈局時所給出的相應的Demo, 下方的Demo所對應的源碼也在Gitbub上進行了分享。仍是那句話,今天博客的內容依然是對UICollectionView的應用。佈局
UICollectionView這個控件是很是強大的,之因此強大,源於其可定製性比較高,靈活多變。測試
2、控件的調用spa
咱們將上述分類選擇的控件進行了封裝,接下來,咱們將會給出其初始化和調用的方式。下方就是咱們所封裝控件的調用方式,下方的二維數組dataSource就是咱們所封裝控件中的CollectionView中的數據源,該數據源中的數據項要遵循咱們指定的CEThemeDataSourceProtocal協議。稍後咱們會給出該協議中因此對應的內容。設計
DataSourceTools類中的createDataSource()類方法就負責建立咱們須要的測試數據。數據源建立好後,在實例化CESelectThemeController對象時,將相應的數據源傳給咱們的控件便可。而後給控件的對象設置更新數據源的閉包回調,也就是說,當咱們使用該封裝的控件對DataSource操做完畢後,會執行下方的閉包回調,將更新後的數據源傳給調用者。以下所示:3d
CEThemeDataSourceProtocal協議就規範了數據源中的數據項必需要實現的方法,下方就是CEThemeDataSourceProtocal協議的實現代碼。固然該協議的代碼實現比較簡單,就一個menuItemName()方法,該方法的返回值是一個字符串。該字符串就是咱們要在Cell上顯示的Menu的名字。
下方就是建立咱們的數據項的測試數據相關代碼。下方的MeteData類就是咱們要在上述控件測Cell中顯示的數據。該類實現了CEThemeDataSourceProtocal協議,並給出了menuItemName()的方法實現。
在DataSourceTools中的createDataSource()方法中負責建立咱們的測試數據,經過循環實例化MeteData並存入二維數組中,並將該二維數據組進行返回。該方法返回的二維數組就是咱們須要的數據源。
3、控件核心代碼介紹
上面咱們簡單介紹了該控件的調用方式,接下來咱們來看一下該控件的核心代碼的實現。說吧了,就是長按手勢識別以及CollectionView的Cell的移動。下方咱們將詳細的介紹一下該控件的核心代碼的實現。
1. UICollectionViewDataSource
下方就是該控件中使用UICollectionView的DataSource的代理方法。前面幾個咱們以前介紹過的代理方法就不作過多贅述了,下方兩個畫框的就是本篇博客的主角,一個是開啓Cell移動的代理方法,另外一個是移動後更新數據源的方法,具體以下所示。
二、爲CollectionView添加長按手勢
接下來要作的就是給CollectionView添加LongPressGestureRecognize。addGestureRecognizer()方法負責爲咱們的CollectionView添加長按手勢,longPress()方法就是該長按手勢所觸發的方法。手勢開始時,咱們調用longPressBegin()方法。手勢改變時,咱們調用longPressChange()方法。手勢結束時,咱們調用longPressEnd()。這三個方法是本篇博客的關鍵,下方會具體給出其實現方式。
三、longPressBegin()方法的實現
下方是長按手勢開始時所觸發的方法,首先根據觸摸的點來獲取該點所在cell的IndexPath。若是該Cell不是第一個Section中的Cell, 那麼就不觸發手勢開始的事件,由於咱們規定只有第一個Section中的Cell纔有長按拖動手勢。
若是Cell符合咱們的要求,咱們就調用UICollectionView的beginInteractiveMovementForItem()方法來啓動移動Item功能。固然,該方法是iOS9之後才添加的。啓動後咱們將當前的Cell隱藏,而後將當前的Cell生成快照,讓後讓該快照跟着咱們的手指移動便可。具體代碼以下所示:
四、longPressChange()方法的實現
下方方法就是手指移動時所觸發的方法,該方法的代碼比較簡單,主要是改變咱們快照的座標,讓Cell的快照隨着手指的移動而移動。而後再調用updateInteractiveMovementTargetPosition()。調用該方法時,會執行DataSource代理中更新數據源的代理方法,也就是上面DataSource代理方法中最後一個更新數據源的方法。
五、longPressEnd()方法實現
該方法的主要功能是在手勢結束後作一些善後工做,如結束移動,而後移除掉Cell的快照並顯示隱藏掉的cell。具體以下所示:
今天的博客就先介紹到這兒吧,上面只是本篇博客所涉及Demo的一小部分代碼,完整的代碼請移步於下方的github分享連接。
github代碼分享連接:https://github.com/lizelu/CESelectThemes