StackView
心情不是很好,也抬不起太大的興趣來寫代碼。隨便拿了個之前寫的代碼做個小小的講解。
Reason
最近可能要用到一個疊起來的View容器,但是似乎網上沒有非常合適組件(也可能是我沒有深挖),之前我的一位同事做過一個這樣的組件,但是沒有發(fā)布出來,我看了一下實現(xiàn)的源代碼,做了一些改動,并做成了組件,發(fā)布到了Pod上。
做法
這個容器是我重新用View來寫的,而且寫的比較笨拙,如果有好的改動,歡迎fork我在Github上面的代碼,并提交pull request。</br>
不可否認的是,這肯定是可以通過自定義CollectionViewLayout來實現(xiàn)的,將來可能會帶來用CollectionViewLayout來實現(xiàn)的代碼,可能還會實現(xiàn)Swift版本,同樣很歡迎大家來幫忙寫一些代碼并pull request上來。</br>
那我們來一起看一看代碼:
/**
* It's a property save cells and handle cell actions
*
*/
@property (nonatomic, strong) StackViewDefaultPile *pile;
/**
* The components datasource
*
*/
@property (nonatomic, weak) id<StackViewDatasource> datasource;
/**
* Reload data clear all cell and readd cells into component
*
*/
- (void)reloadData;
/**
* Get Cell with Reuseid
*
*/
- (UIView *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;
/**
* regist cell with nibname and id
*
*/
- (void)registerCellWithNibName:(NSString *)nibName forCellReuseIdentifier:(NSString *)identifier;
先看屬性
-
@property (nonatomic, strong) StackViewDefaultPile *pile定義了一個StackViewDefaultPile類型的屬性,這邊是我之前的寫法,現(xiàn)在應該變了,這是一個管理組件內部View的堆,在之后的代碼中,我抽離了StackViewPile的公共接口,定義了BaseStackViewPie,使用者可以自定義StackViewPile,只要和StackViewDefaultPile一樣實現(xiàn)了BaseStackViewPie的接口就好了。</br> -
@property (nonatomic, weak) id<StackViewDatasource> datasource;定義了StackViewComponent的數據源,這和UITableView和UICollectionView一樣。(還沒有加上delegate)將來有空會加上。</br>
方法(幾乎按照標準的UITableView和UICollectionView來設計)
-
- (void)reloadData;重新讀取這個組件的數據,并且渲染。</br> -
- (UIView *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndex:(NSInteger)index;用過重用的id獲取注冊的View的對象</br> -
registerCellWithNibName:(NSString *)nibName forCellReuseIdentifier:(NSString *)identifier;通過重用id和資源文件名注冊View的對象
StackViewDatasource
-
- (UIView *)stackView:(StackViewComponent *)stackView cellForIndex:(NSInteger)index通過index返回一個當前的View的對象。 -
- (CGSize)stackViewCellSize:(StackViewComponent *)stackView返回每個View的大小 -
- (NSInteger)stackViewNumberOfRow:(StackViewComponent *)stackView返回總共View的個數
實現(xiàn)文件
-
- (void)awakeFromNib很慚愧,暫時只適用于從xib中加載這個組件。因此,初始化的操作幾乎都放在了- (void)awakeFromNib中,在- (void)awakeFromNib中一共包含了兩個步驟,分別是初始化一些內部屬性,初始化Views(暫時只有加入手勢) -
- (void)setDatasource:(id<StackViewDatasource>)datasourcedatasource發(fā)生改變的時候,我們需要reloadData -
- (void)reloadData分為兩個步驟,將所有的View移除并重置pile,然后重新渲染所有的pile上的View -
- (void)panGestureDidBegin:(UIPanGestureRecognizer *)gesture當手勢要開始的時候記錄當前的位置 -
- (void)panGestureDidMove:(UIPanGestureRecognizer *)gesture根據手勢移動的位置調整pile -
- (void)panGestureDidEnd:(UIPanGestureRecognizer *)gesture在手勢結束的時候判斷并使用動畫復原或者變化
pile
@property (nonatomic, strong) NSArray *alphaArray;
@property (nonatomic, strong) NSArray *zTransformArray;
@property (nonatomic, assign) CGFloat rangeLength;
@property (nonatomic, strong) UIView *previousCell;
@property (nonatomic, strong) UIView *nextCell;
@property (nonatomic, assign) CATransform3D cellTransform;
- (void)reset;
- (void)recover;
- (void)pushNextCell;
- (void)pushPreviousCell;
- (UIView *)cellOfIndex:(NSInteger)index;
- (void)setCell:(UIView *)cell atIndex:(NSInteger)index;
- (UIView *)removeCellAtIndex:(NSInteger)index;
- (UIView *)bringPreviousCellToTop;
- (UIView *)bringNextCellToBottom;
- (NSInteger)maxSize;
- (void)resetCell:(UIView *)cell atIndex:(NSInteger)index;
- (void)updateCellWithOffset:(CGFloat)offset;
這些代碼就不多做解釋了,要想自定義Pile,只要像StackViewDefaultPile一樣實現(xiàn)
- (NSInteger)maxSize, - (void)reset, - (UIView *)cellOfIndex:(NSInteger)index, - (void)setCell:(UIView *)cell atIndex:(NSInteger)index方法,并定義幾個View,關于一些屬性alphaArray,zTransformArray,rangeLength可以自己定義,產生更好地疊加效果