iOS图片预览

背景
原先项目内的图片预览框架用的是一个魔改的某开源框架, 里面的代码又杂又乱, 各种乱拷贝代码. 这周公司的项目任务已经做完, 就决定给这个框架自己重写一下.

效果 点我去看效果

  • 支持单图/多图点开按顺序预览
  • 支持单张放大/缩小
  • 支持从头部和尾部插入列表
  • 支持滑动回收预览
  • 图片可以是GIF
  • 支持将图片保存入系统相册

实现

  • 主体使用UIScrollView, 然后利用UIScrollViewDelegate- scrollViewDidZoom:- viewForZoomingInScrollView:配合, 实现滚动、滑动和放大缩小功能.
    • 此处需要注意的是: 层级结构为: main UIScrollView -> [sub UIScrollView -> UIView -> SDAnimationImageView], 不然在拖拽时候会出现显示异常
    • sub UIScrollView- scrollViewDidZoom:中需要重设 - viewForZoomingInScrollView: 的位置.
      1
      2
      3
      4
      5
      6
      CGFloat ratio = MIN(self.bounds.size.width / size.width, self.bounds.size.height / size.height);
      CGFloat W = ratio * size.width;
      CGFloat H = ratio * size.height;
      CGRect imageFrame = CGRectMake((self.bounds.size.width - W) / 2, (self.bounds.size.height - H) / 2, W, H);
      self.containerView.frame = imageFrame;
      self.imageView.frame = CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height);
    • 给主体控件上添加UITapGestureRecognizer手势, 实现在拖拽的时候进行回收/重新布局. 主要的
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      - (void)handlePanGestureRecognizer:(UIPanGestureRecognizer *)sender {
      static LRSImagePreviewZoomingImageView *currentView = nil;
      if (sender.state == UIGestureRecognizerStateBegan) {
      /// 在手势开始的时候获取当前正在拖拽的自视图
      currentView = ...;
      }
      if (currentView) {
      if (sender.state == UIGestureRecognizerStateEnded) {
      /// 重置
      currentView = nil;
      } else {
      /// 拖拽动画
      CGPoint p = [sender translationInView:self];
      CGAffineTransform transform = CGAffineTransformMakeTranslation(p.x, p.y);
      CGFloat value = 1 - (MAX(fabs(p.x), fabs(p.y))) / 1000;
      transform = CGAffineTransformScale(transform, value, value);
      currentView.transform = transform;
      }
      }
      }
    • 因为还需要从图片点击位置出现/回收视图, 所以还需要记录弹出预览图的点击位置.
    • 往头部插入数据的时候, 记得设置Scroview的偏移量
    • 需要支持GIF, 所以我们引用了SDWebImage
    • 图片保存系统相册, 我们使用了系统的Photos框架
      1
      2
      3
      4
      5
      6
      + (void)creationRequestWithData:(NSData *)data options:(nullable PHAssetResourceCreationOptions *)options completionHandler:(void (^)(BOOL, NSError * _Nullable))handler {
      PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
      [library performChanges:^{
      [[PHAssetCreationRequest creationRequestForAsset] addResourceWithType:PHAssetResourceTypePhoto data:data options:options];
      } completionHandler:handler];
      }

注意点

  • 坐标换算
    CGRect rect = [A convertRect:B.frame fromView:B.supverView]
    得到的rect就是B相对于A的新坐标.

demo地址
已经上传github, enjoy