這幾天在做項目的時候,碰到了要用圖片瀏覽器的需求,在網(wǎng)上找了一些資料,發(fā)現(xiàn)大多的做法不是說很好理解,然后就自己試著用UICollectionView寫了簡單的圖片瀏覽器,做了簡單的過渡動畫,也可以實現(xiàn)圖片的縮放。
下圖是基礎(chǔ)的效果:
演示demo.gif

演示demo2.gif
接下來是大致的步驟講解:
demo1界面的搭建
- 首先我們需要利用創(chuàng)建一個控制器,然后在控制器上面搭建collectionView
- collectionView的創(chuàng)建首先創(chuàng)建UICollectionViewFlowLayout 的對象,設(shè)置布局的滾動方式,和每個item的尺寸, 然后創(chuàng)建collecitonView
UICollectionViewFlowLayout * layout = [[UICollectionViewFlowLayout alloc]init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.itemSize = CGSizeMake(SCREENWIDTH / 4 - 1, SCREENWIDTH / 4 - 1);
_collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];
_collectionView.frame = CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT);
_collectionView.contentInset = UIEdgeInsetsMake(45 * W, 0, 57, 0);
[self.view addSubview:_collectionView];
- 接下來設(shè)置好代理 并注冊cell,來讓cell進行循環(huán)利用
_collectionView.delegate = self;
_collectionView.dataSource = self;
//注冊cell
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"table"];
- 接下來實現(xiàn)數(shù)據(jù)源的方法,然后在接下來的幾個方法
//每組中item的個數(shù)
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section;
//cell的創(chuàng)建和數(shù)據(jù)的提供
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath;
//每行之間的最小間距
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section;
//每個item(cell)的最小間距
-(CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section;
//選中cell時候要執(zhí)行的操作
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
//在這個里面我們要完成將indexPath第二個界面的操作
}
我忽略了數(shù)據(jù)提供的具體操作,自己可以找數(shù)據(jù)實現(xiàn)上面的數(shù)據(jù)源方法,然后這時候得到的界面應(yīng)該如下圖所示:

Paste_Image.png
第二個界面的搭建
這時候我們有兩種做法可以參考:
- 一種是直接跳轉(zhuǎn)另一個控制器,在控制器中再創(chuàng)建collectionView,進行相應(yīng)的操作
- 我們直接自定義一個View,在View上面直接創(chuàng)建collectionView,然后直接把這個View在需要的時候利用KeyWindow改到第一個控制器上面,在我們需要的時候再進行移除
我選擇的是第二種方法
- 我們直接自定義1個View,設(shè)置View和屏幕的寬高相同,然后直接定義collectionView,和上面第一個界面的搭建大同小異,只需要把每個item的大小直接設(shè)置為屏幕的大小。滾動的方向設(shè)置為水平滾動。
//滾動的方向設(shè)置為水平滾動
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
layout.itemSize = CGSizeMake(SCREENWIDTH, SCREENHEIGHT);
- 接下來我們需要自定義cell來完成接下來的操作,拿到第一個頁面indexPath,然后根據(jù)indexPath.row計算出初始化的時候,我們colletionView的偏移量,來進行定位我們到底選擇了哪一張圖片,而且我們兩組數(shù)據(jù)其實用的是同一組數(shù)據(jù)源。
self.collectionView.contentOffset = CGPointMake(SCREENWIDTH * index.row, 0);
到現(xiàn)在我們兩個界面的搭建基本完畢,最關(guān)鍵的一點是實現(xiàn)界面的交互,和第二個界面的圖片的縮放
縮放問題
- 我們需要在自定義的cell里面放入等同屏幕大小的scrollView,并設(shè)置如下的屬性:
self.artScrollView = [[UIScrollView alloc] init];
self.artScrollView.frame = CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT);
self.artScrollView.minimumZoomScale = 0.5;
self.artScrollView.maximumZoomScale = 3.0;
self.artScrollView.showsVerticalScrollIndicator = NO;
self.artScrollView.showsHorizontalScrollIndicator = NO;
self.artScrollView.delegate = self;
[self.contentView addSubview:self.artScrollView];
- 然后在模型的set方法中,完成UIimageView的創(chuàng)建和設(shè)置
UIImageView *textimage = [[UIImageView alloc] initWithImage:image];
//移除上一個artimage
[self.artimage removeFromSuperview];
self.artimage = [[UIImageView alloc] init];
self.artimage.contentMode = UIViewContentModeScaleAspectFit;
self.artimage.frame = [self setImage:textimage];
self.artimage.image = image;
[self.artScrollView addSubview:self.artimage];
//設(shè)置scroll的contentsize的frame
self.artScrollView.contentSize = self.artimage.frame.size;
- 設(shè)置scrollView的縮放內(nèi)容
//這個方法的返回值決定了要縮放的內(nèi)容(只能是UISCrollView的子控件)
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.artimage;
}
- 而接下來兩個方法則是實現(xiàn)圖片縮放時候讓圖片仍然居中,和設(shè)置imageView的frame來讓圖片根據(jù)自己的大小,自適應(yīng)屏幕
//控制縮放是在中心
- (void)scrollViewDidZoom:(UIScrollView *)scrollView
{
CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)?
(scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;
CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?
(scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;
self.artimage.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,
scrollView.contentSize.height * 0.5 + offsetY);
}
//根據(jù)不同的比例設(shè)置尺寸
-(CGRect) setImage:(UIImageView *)imageView
{
CGFloat imageX = imageView.frame.size.width;
CGFloat imageY = imageView.frame.size.height;
CGRect imgfram;
CGFloat CGscale;
BOOL flx = (SCREENWIDTH / SCREENHEIGHT) > (imageX / imageY);
if(flx)
{
CGscale = SCREENHEIGHT / imageY;
imageX = imageX * CGscale;
imgfram = CGRectMake((SCREENWIDTH - imageX) / 2, 0, imageX, SCREENHEIGHT);
return imgfram;
}
else
{
CGscale = SCREENWIDTH / imageX;
imageY = imageY * CGscale;
imgfram = CGRectMake(0, (SCREENHEIGHT - imageY) / 2, SCREENWIDTH, imageY);
return imgfram;
}
}
第二個界面的縮放處理完畢,接下來時如何顯示在第一個界面上
- 我們利用KeyWindow可以使第二個界面View直接蓋在第一個界面的上面,而要做動畫操作,大家可以看下我的做法理解下(原理就是利用蒙版先做動畫效果,然后讓第二個界面直接蓋上去,移除的時候先用CGD定時器延時讓View透明,然后在這個時間之后直接移除View就可以)
#第一個界面cell被選中的時候調(diào)用的代理方法進行如下操作
UIView * backview = [[UIView alloc]initWithFrame:self.view.bounds];
backview.backgroundColor = [UIColor blackColor];
openartModel * model = self.objcArray[indexPath.row];
//計算位置
CGFloat startX = indexPath.row % 4 * ((SCREENWIDTH - 10) /4) + 15;
CGFloat startY = indexPath.row / 4 * ((SCREENWIDTH - 10) /4)+ 84;
CGFloat animatime = 0.7;
UIImageView * imageview = [[UIImageView alloc]initWithFrame:CGRectMake(startX,startY, ((SCREENWIDTH - 10) /4), ((SCREENWIDTH - 10) /4))];
//加載圖片
NSString * str = [NSString stringWithFormat:@"http://www.artp.cc/%@",model.ARTWORK_FILE_ORIGINAL];
imageview.image = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:str];
imageview.contentMode = UIViewContentModeScaleAspectFit;
[[UIApplication sharedApplication].keyWindow addSubview:backview];
[[UIApplication sharedApplication].keyWindow addSubview:imageview];
//設(shè)置動畫顯示
[UIView animateWithDuration:animatime animations:^{
CGRect frame = CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT);
imageview.frame = frame;
}];
//添加新的view
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animatime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
DetailArtView * detailView = [[DetailArtView alloc] initWithFrame:CGRectMake(0, 0, SCREENWIDTH, SCREENHEIGHT) AndIndex:indexPath];
detailView.objcArray = self.objcArray;
[[[[UIApplication sharedApplication].keyWindow subviews] lastObject] removeFromSuperview];
[[[[UIApplication sharedApplication].keyWindow subviews] lastObject] removeFromSuperview];
[[UIApplication sharedApplication].keyWindow addSubview:detailView];
});