iOS图片浏览器一

之前有一个项目中用到了类似于微信的图片查看器,也看了网上很多开源的 总感觉不是自己想要的 这里就自己动手写一个 打算跟微信写的差不多吧 用起来也是跟微信很像

效果

先看一下初步效果 这是还没实现完的 一部分
photoBrower

我们先来分析一下图片浏览器 可以多张浏览 可以下载图片观看 可以手势缩放

分析

综合以上几点我们可以得出以下几点:

  • 图片需要下载,这里我们就用SDWebImage
  • 需要多张浏览滑动,肯定是用一个UIScrollView包裹起来
  • 每张图片需要能够适应手势缩放,所以每张图片也是用一个UIScrollView包起来
  • 还要考虑一个 是查看本地图片还是查看网络图片,如果一张图片既有本地图片也有网络地址,那么肯定是优先查看本地的图片

综合以上几点,我们就可以开始了:

创建photo实例

首先创建一个Photo实例 用来存储照片的一些属性

.h文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#import <UIKit/UIKit.h>

@interface Photo : UIImageView


/**
* 缩略图 imageView
*/
@property (nonatomic, strong) UIImageView *thumbnail;

/**
高清图
如果存在 则在显示的时候优先显示设置的本地大图
*/
@property (nonatomic, strong) UIImage *fullImage;


/**
* 大图URL 存在本地大图时 还是优先显示本地大图
*/
@property (nonatomic,strong) NSString *fullImgUrl;


/**
创建图片实例

@param thumbnail 缩略图View 用于加载在下载图片的时候
@param fullImage 高清图 image
@param fullImgUrl 高清图地址

@return photo实例
*/
- (instancetype)initWithThumbnail:(UIImageView *)thumbnail fullImage:(UIImage *)fullImage fullImgUrl:(NSString *)fullImgUrl;


@end

.m文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

@implementation Photo

/**
将图片的一些实例

@param thumbnail 含缩略图的view
@param fullImage 高清大图
@param fullImgUrl 高清大图网络地址

@return 照片model实例
*/
- (instancetype)initWithThumbnail:(UIImageView *)thumbnail fullImage:(UIImage *)fullImage fullImgUrl:(NSString *)fullImgUrl{
self = [super init];
if (self) {
//设置照片填充模式 可点击
self.clipsToBounds = YES;
self.userInteractionEnabled = YES;
self.contentMode = UIViewContentModeScaleAspectFill;
_thumbnail = thumbnail;
_fullImage = fullImage;
_fullImgUrl = fullImgUrl;
}
return self;
}

@end

创建Brower

照片实例创建好 接下来 需要做的 就是展示的view

查看照片的时候 我们都知道 是照片view整个覆盖上屏幕 那么这个view肯定是加在最上层的 怎么加在最上层呢

直接加在第一层Window上 即 [UIApplication sharedApplication].keyWindow

在PhotoBrower中 我只暴露了一个方法

1
2
3
4
5
6
7
8
9
10
11
@interface PhotoBrower : UIView

/**
显示大图

@param photos 照片数组 装的Photo
@param index 当前的照片是第几张
*/
+ (void)showWithPhotos:(NSArray *)photos index:(NSInteger)index;

@end

在Brower的实现中

首先需要创建黑色的背景

1
2
3
4
5
6
7
8
9
10
/**
创建黑色的背景
*/
- (void)createBlackView{
UIView *blackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
blackView.backgroundColor = [UIColor blackColor];
[self addSubview:blackView];
self.blackView = blackView;
self.blackView.alpha = 0;
}

然后创建外部最大的滑动的UIScrollView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
创建外部的 滑动的scrollview
*/
- (void)createOuterScrollView{
UIScrollView *outScrollView = [[UIScrollView alloc] init];
outScrollView.backgroundColor = [UIColor clearColor];
outScrollView.delegate = self;//这个地方的代理主要是做外部Scroll滑动的时候 处理
outScrollView.tag = OutScrollVIewTag;//用于判断处理点击事件和缩放事件时判断是否是外部的UIScrollView
outScrollView.pagingEnabled = YES;
outScrollView.bounces = YES;
outScrollView.showsHorizontalScrollIndicator = NO;
outScrollView.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
[self addSubview:outScrollView];
self.outScrollView = outScrollView;
}

实现UIScrollView的拖动代理

1
2
3
4
5
6
7
8
9
10
11
12
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
int currentIndex = scrollView.contentOffset.x/SCREEN_WIDTH;
if (self.currentIndex!=currentIndex && scrollView.tag==OutScrollVIewTag) {
self.currentIndex = currentIndex;
for (UIView *view in scrollView.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
UIScrollView *scrollView = (UIScrollView *)view;
scrollView.zoomScale = 1.0;
}
}
}
}

在做显示动画的时候 需要转换一下view 然后做一个动画

具体实现 我们还是看代码

1
2
3
4
5
6
7
8
#pragma mark 获取原始frame 为了做动画
-(void)setupOriginRects{
for (Photo *photo in self.photos) {
UIImageView *sourceImageView = photo.thumbnail;
CGRect sourceF = [YQKeyWindow convertRect:sourceImageView.frame fromView:sourceImageView.superview];
[self.originRects addObject:[NSValue valueWithCGRect:sourceF]];
}
}

讲数组中的view的原始frame获取出来 在显示时做一个动画

接下来 就是创建每个单独的photo了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
创建每一张照片 每一张照片都是一个scrollview
scrollview可缩放
*/
-(void)setupphotoScrollViews{
for (int i=0; i<self.photos.count; i++) {
UIScrollView *photoScrollView = [[UIScrollView alloc] init];
photoScrollView.backgroundColor = [UIColor clearColor];
photoScrollView.tag = i;
photoScrollView.frame = CGRectMake(SCREEN_WIDTH*i, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
photoScrollView.delegate = self;
photoScrollView.maximumZoomScale=2.0;
photoScrollView.minimumZoomScale=1;
[self.outScrollView addSubview:photoScrollView];

Photo *photo = self.photos[i];
UITapGestureRecognizer *photoTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoTap:)];
UITapGestureRecognizer *zonmTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zonmTap:)];
zonmTap.numberOfTapsRequired = 2;
[photoScrollView addGestureRecognizer:photoTap];
[photoScrollView addGestureRecognizer:zonmTap];
[photoTap requireGestureRecognizerToFail:zonmTap];

[photoScrollView addSubview:photo];
//有本地高清大图 直接大图显示出来就不需要再次访问网络
if (photo.fullImage) {
photo.image = photo.fullImage;
photo.frame = [self.originRects[i] CGRectValue];
[UIView animateWithDuration:0.3 animations:^{

self.blackView.alpha = 1.0;

CGFloat ratio = (double)photo.image.size.height/(double)photo.image.size.width;

CGFloat bigW = SCREEN_WIDTH;
CGFloat bigH = SCREEN_WIDTH*ratio;

photo.bounds = CGRectMake(0, 0, bigW, bigH);
photo.center = CGPointMake(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
}];
return;
}
NSURL *fullImgUrl = [NSURL URLWithString:photo.fullImgUrl];
[photo sd_setImageWithURL:fullImgUrl placeholderImage:nil options:SDWebImageRetryFailed | SDWebImageLowPriority progress:^(NSInteger receivedSize, NSInteger expectedSize) {
//开始下载 这里后面会做一些效果 比如下载的进度条 一个load
} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image!=nil) {
photo.frame = [self.originRects[i] CGRectValue];
//如果是网上下载下来的图片 那么改变一下photo的位置 后面做动画 会和已有缓存的图片显示效果不一样
if (cacheType==SDImageCacheTypeNone) {
photo.frame = CGRectMake(0, 0, SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
photo.center = CGPointMake(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
}
[UIView animateWithDuration:0.3 animations:^{
self.blackView.alpha = 1.0;
CGFloat ratio = (double)photo.image.size.height/(double)photo.image.size.width;
CGFloat bigW = SCREEN_WIDTH;
CGFloat bigH = SCREEN_WIDTH*ratio;
photo.bounds = CGRectMake(0, 0, bigW, bigH);
photo.center = CGPointMake(SCREEN_WIDTH/2, SCREEN_HEIGHT/2);
}];
}else{
//下载错误 提示一个 错误需要
}
}];
}
}

第一部分的主要代码 就在这里了 后面还会继续完善 加上下载loading 加上长按图片保存等操作

项目的源码放在了

https://github.com/yangqian111/blog/tree/master/iOS图片查看器