如何實現一個圖片瀏覽器

weixin_34054866發表於2018-02-12

實現效果

3286073-1af5d87a1a427cb1.gif
PhotoBrowser.gif

目錄結構

3286073-28ce6ba596712f0d.png
image.png

呼叫方法

  1. 不帶過渡動畫,直接新增圖片瀏覽器到window上
/**
 * 檢視本地圖片(不帶過渡動畫,直接加到window上)
 * urls 大圖的url陣列
 */
+ (PDPhotoBrowser *)photoWithImages:(NSArray *)images;

/**
 * 檢視網路圖片(不帶過渡動畫,直接加到window上)
 * urls 大圖的url陣列
 */
+ (PDPhotoBrowser *)photoWithUrls:(NSArray *)urls;

  1. 附帶微信圖片瀏覽器一樣的過渡動畫
/*
 * 檢視本地圖片(帶過渡動畫)
 * 用image陣列快速建立圖片瀏覽器
 * currentIndex 當前操作的下標
 * animateView 獲取縮放返回的imageView的回撥block
 */
+ (PDPhotoBrowser *)photoWithImages:(NSArray *)images currentIndex:(NSInteger)currentIndex animateView:(PDAnimateView)animateView;

/*
 * 檢視網路圖片(帶過渡動畫)
 * urls 大圖的url陣列
 * currentIndex 當前操作的下標
 * animateView 獲取縮放返回的imageView的回撥block
 */
+ (PDPhotoBrowser *)photoWithUrls:(NSArray *)urls currentIndex:(NSInteger)currentIndex animateView:(PDAnimateView)animateView;

實現原理

  1. 利用UICollectionView實現圖片瀏覽
  2. UICollectionView的Cell底部是一個UIScrollView,在_scrollView上新增UIImageView用來展示圖片,新增自定義的progressView用來顯示載入進度
  3. UICollectionView的Cell新增單擊手勢退出圖片瀏覽器,雙擊手勢放大圖片,長按手勢彈出操作框
  4. 根據圖片和螢幕比例關係,調整最大和最小伸縮比例,和換算長圖的寬高
  • 如果圖片寬度比螢幕寬度小,將圖片設定為螢幕等寬,根據比例換算高度
  • 如果圖片是橫向長圖,調整imageView大小為圖片實際尺寸將_scrollView的contentSize寬度設定為圖片實際寬度,調整imageView的center,設定_scrollView的contentSize確保橫向滾動
  • 如果圖片是豎向長圖,調整imageView大小為圖片實際尺寸將_scrollView的contentSize高度設定為圖片實際高度,調整imageView的center,設定_scrollView的contentSize確保眾向滾動
  • 設定_scrollView的最大最小縮放比例
/**
 *  根據圖片和螢幕比例關係,調整最大和最小伸縮比例
 */
- (void)setMaxAndMinZoomScales
{
    // self.photoImageView的初始位置
    UIImage *image = self.imageView.image;
    if (image == nil || image.size.height == 0) {
        return;
    }
    CGFloat imageWidthHeightRatio = image.size.width / image.size.height;
    
    CGRect imageViewFrame = CGRectZero;
    imageViewFrame.size.width = _scrollView.frame.size.width;
    imageViewFrame.size.height = _scrollView.frame.size.width / imageWidthHeightRatio;
    imageViewFrame.origin.x = 0;
    
    //垂直方向長圖
    if (imageViewFrame.size.height > _scrollView.frame.size.height) {
        imageViewFrame.origin.y = 0;
        _scrollView.scrollEnabled = YES;
    } else {
         imageViewFrame.origin.y = (_scrollView.frame.size.height -  imageViewFrame.size.height ) * 0.5;
        _scrollView.scrollEnabled = NO;
    }
    
    self.imageView.frame = imageViewFrame;

    _scrollView.maximumZoomScale = MAX(_scrollView.frame.size.height / self.imageView.bounds.size.height, 3.0);
    _scrollView.minimumZoomScale = 1.0;
    _scrollView.zoomScale = 1.0;
    _scrollView.contentSize = CGSizeMake(imageViewFrame.size.width, MAX(imageViewFrame.size.height, _scrollView.frame.size.height));
}
  1. 新增開啟圖片瀏覽器和退出時的過渡動畫
  • 先獲取點選的view,將view從原父容器座標轉換到圖片瀏覽器的座標,記為開始座標
  • 換算view動畫完成的座標,記為目的座標
  • 建立一個臨時的動畫view,來完成從開始座標到目的座標的動畫
  • 退出圖片瀏覽器的動畫反之
/**
 *  開始開啟相簿的過渡動畫
 */
- (void)beginShowTransfromAnimation
{
    //獲取到使用者點選的那個UIImageView物件,進行座標轉化
    CGRect startRect;
    if (self.animateView) {
        _animateImageView = self.animateView(_currentIndex);
    }
    startRect = [self.animateImageView.superview convertRect:self.animateImageView.frame toView:self];
    
    //利用零時tempImageView完成過度的形變動畫
    UIImageView *tempImageView = [[UIImageView alloc] init];
    
    UIImage *image = self.animateImageView.image;
    if (!image) {
        image = [UIImage imageNamed:@"pb_placeHolder"];
    }
    tempImageView.image = image;
    tempImageView.frame = startRect;
    [self addSubview:tempImageView];
    
    CGRect targetRect; // 目標frame
    CGFloat imageWidthHeightRatio = image.size.width / image.size.height;
    CGFloat width = self.bounds.size.width;
    CGFloat height = self.bounds.size.width / imageWidthHeightRatio;
    CGFloat x = 0;
    CGFloat y;
    if (height > self.bounds.size.height) {
        y = 0;
    } else {
        y = (self.bounds.size.height - height ) * 0.5;
    }
    targetRect = CGRectMake(x, y, width, height);
    _collectionView.hidden = YES;
    self.alpha = 1.0;
    
    // 動畫修改圖片檢視的frame,居中同時放大
    [UIView animateWithDuration:0.3 animations:^{
        tempImageView.frame = targetRect;
    } completion:^(BOOL finished) {
        [tempImageView removeFromSuperview];
        _collectionView.hidden = NO;
    }];
}

PDPhotoBrowser是基於collectionView實現的圖片瀏覽器,詳情請點選Demo地址

相關文章