![result](http://static.javashuo.com/static/loading.gif)
準備數據
首先先加入一些資源文件:app
先創建一個xcassets
文件,放入圖片:ide
![xcassets](http://static.javashuo.com/static/loading.gif)
再創建一個plist文件,寫入與圖片對應的內容:佈局
![plist](http://static.javashuo.com/static/loading.gif)
在ViewController中讀取plist
到詞典中:post
@property (nonatomic, strong) NSArray *itemTitles;
NSString *path = [[NSBundle mainBundle] pathForResource:@"titles" ofType:@"plist"]; NSDictionary *rootDictionary = [[NSDictionary alloc] initWithContentsOfFile:path]; self.itemTitles = [rootDictionary objectForKey:@"heros"];
|
能夠打log
輸出,能夠看到plist
的內容已經讀取出來,後面就能夠用_itemTitle
做爲數據源了。優化
添加UICollectionView初步顯示圖片
每一個CollectionView
都有一個對應的佈局layout
,對於默認的的UICollectionViewFlowLayout
,效果是相似Android的GridView
的佈局。若是要自定義CollectionView
的樣式,就要對這個layout
進行修改。ui
創建本身的HorizontalFlowLayout
,繼承自UICollectionViewFlowLayout
,而後在初始化方法裏將滾動方向設置爲水平:atom
- (instancetype) init { if (self = [super init]) { self.scrollDirection = UICollectionViewScrollDirectionHorizontal; } return self; }
|
接下來定製咱們的cell
的顯示樣式,創建DotaCell
,繼承自UICollectionViewCell
。因爲咱們要實現的是圖片和文字的上下佈局,因此增長兩個屬性:spa
@interface DotaCell : UICollectionViewCell
@property (nonatomic, strong) UIImageView *image; @property (nonatomic, strong) UILabel *name;
@end
|
而後設置圖片與文字上下對齊佈局,這裏我使用pod
導入Masonry
庫來寫自動佈局:代理
- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initialize]; } return self; }
- (void)initialize { self.layer.doubleSided = NO; self.image = [[UIImageView alloc] init]; self.image.backgroundColor = [UIColor clearColor]; self.image.contentMode = UIViewContentModeCenter; self.image.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.name = [[UILabel alloc] init]; self.name.font = [UIFont fontWithName:@"Helvetica Neue" size:20]; self.name.textAlignment = NSTextAlignmentCenter; [self.contentView addSubview:self.image]; [self.contentView addSubview:self.name];
[_image mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self.contentView); make.top.equalTo(self.contentView).offset(30); make.bottom.equalTo(_name.mas_top).offset(-10); }]; [_name mas_makeConstraints:^(MASConstraintMaker *make) { make.left.right.equalTo(self.contentView); make.top.equalTo(_image.mas_bottom).offset(10); make.bottom.equalTo(self.contentView).offset(-20); }]; }
|
寫好layout
和cell
後就能夠用這兩個類來初始化咱們的collectionView
了:code
添加UICollectionViewDataSource
的代理方法,使其顯示數據。
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { return [self.itemTitles count]; }
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { DotaCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:NSStringFromClass([DotaCell class]) forIndexPath:indexPath]; cell.image.image = [UIImage imageNamed:[self.itemTitles objectAtIndex:indexPath.row]]; cell.name.text = [self.itemTitles objectAtIndex:indexPath.row]; return cell; }
|
這樣程序就有了咱們想要的初步效果:
![gif1](http://static.javashuo.com/static/loading.gif)
圖片水平排放
但…效果的確不好!
下面要作的就是逐步完善效果,首先咱們要讓兩排圖像變成一排去展現。那要怎麼去作?首先,咱們在初始化collectionView
的地方設置了高度爲150,因此圖片就擠在這個150的高度裏儘量的壓縮顯示。因爲collectionView
的尺寸已經設定,那麼就剩cell
的尺寸能夠控制了。實現CollectionViewFlowLayoutDelegate
的代理方法sizeForItemAtIndexPath
:
- (CGSize)collectionView:(nonnull UICollectionView *)collectionView layout:(nonnull UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(nonnull NSIndexPath *)indexPath { return CGSizeMake(64, collectionView.bounds.size.height); }
|
這裏寬度64是圖片的尺寸,高度設置填滿collectionView
的高度是爲了防止上圖中兩行圖片擠壓的狀況,因此直接讓一個cell
的高度佔滿整個容器。
這時候的效果好了不少,已經有點樣子了:
![gif2](http://static.javashuo.com/static/loading.gif)
頂端圖片滑到中間
但這離咱們最終的效果還差很遠,接下來我須要實現讓第一張圖片和最後一張圖片都能滑到屏幕中點的位置,這應該是很常見的效果,實現起來也很簡單。首先咱們的一排cell
都默認爲頂端與collectionView
的兩端對齊的,collectionView
的左右兩端與viewController.view
也是對齊的,因此顯示的效果是,兩端的圖片都與屏幕對齊。知道這個關係就好辦了,直接設置collectionView
與其父view
的內間距便可。
依舊是實現flowLayout
的代理方法:
效果如圖:
![gif3](http://static.javashuo.com/static/loading.gif)
居中圖片放大顯示
接下來添加一個咱們須要的特效,就是中間的圖片放大顯示,其他的縮小而且增長一層半透明效果。
在FlowLayout
中有一個名爲layoutAttributesForElementsInRect
的方法,功能如其名,就是設置範圍內元素的layout
屬性。對於這個效果,首先須要設置放大的比例,其次要根據圖片大小和間距來設定一個合適的觸發放大的區域寬度,當圖滑入這個區域就進行縮放。
static CGFloat const ActiveDistance = 80; static CGFloat const ScaleFactor = 0.2;
|
效果以下:
![gif4](http://static.javashuo.com/static/loading.gif)
滑動校訂
這時候幾乎完成了,但還差點東西,就是讓其在滾動中止的時候,離屏幕中間最近的cell
自動矯正位置到中間。仍是在FlowLayout
添加該方法,具體說明我都寫到註釋裏了:
![gif5](http://static.javashuo.com/static/loading.gif)
增長圖片點擊效果
最後 添加一個點擊cell 將其滾動到中間
在viewcontroller
添加CollectionViewDelegate
的代理方法
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { [self.collectionView selectItemAtIndexPath:indexPath animated:YES scrollPosition:UICollectionViewScrollPositionNone]; |
![gif6](http://static.javashuo.com/static/loading.gif)
封裝成控件
當咱們把效果實現以後,就能夠考慮將代碼優化一下,合到一個類裏,減小書寫常量,增長接口,封裝成一個控件去使用。好比能夠設定文字的顯示與隱藏接口,再好比增長適應各類尺寸的圖片等等。這個代碼就不放了,畢竟不難,有問題給我留言好了。