[iOS微博项目

A.微博配图
1.需求
  • 显示原创微博、转发微博的缩略图
  • 4张图使用2x2布局,其他使用3x3布局,最多9张
  • 点击小图放大图片,下载中等图片并显示,使用动画转换
  • 如果是gif文件,在缩略图上加上"gif"标识
 
StatusPhotos
 
2.思路
  • 开始就在微博正文下方创建一个配图区view,创建好9个配图子view
  • 使用一个黑色背景的view来充当大图背景遮盖
  • 使用点击手势唤出大图、缩回大图
 
3.实现
(1)给之前创建的HVWPic类加上中等图片的获取方法
 1 //
 2 //  HVWPic.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/5.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <Foundation/Foundation.h>
10 
11 @interface HVWPic : NSObject
12 
13 /** 缩略图片地址,没有时不返回此字段 */
14 @property(nonatomic, copy) NSString *thumbnail_pic;
15 
16 /** 中等图片 */
17 @property(nonatomic, copy) NSString *bmiddle_pic;
18 
19 @end
 
 1 //
 2 //  HVWPic.m
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/5.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "HVWPic.h"
10 
11 @implementation HVWPic
12 
13 /** 设置缩略图的同时,配置中等图片url */
14 - (void)setThumbnail_pic:(NSString *)thumbnail_pic {
15     _thumbnail_pic = [thumbnail_pic copy]; // 待会要修改此url,所以使用copy
16    
17     // 修改路径地址
18     _bmiddle_pic = [thumbnail_pic stringByReplacingOccurrencesOfString:@"thumbnail" withString:@"bmiddle"];
19 }
20 
21 @end
 
(2)创建一个配图view
 1 //
 2 //  HVWStatusPhotoView.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/28.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 #import "HVWPic.h"
11 
12 @interface HVWStatusPhotoView : UIImageView
13 
14 /** 图片 */
15 @property(nonatomic, strong) HVWPic *pic;
16 
17 @end
 
 1 //
 2 //  HVWStatusPhotoView.m
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/28.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "HVWStatusPhotoView.h"
10 #import "UIImageView+WebCache.h"
11 
12 @interface HVWStatusPhotoView()
13 
14 /** gif logo */
15 @property(nonatomic, weak) UIImageView *gifLogo;
16 
17 @end
18 
19 @implementation HVWStatusPhotoView
20 
21 - (instancetype)initWithFrame:(CGRect)frame {
22     self = [super initWithFrame:frame];
23     if (self) {
24         // 填充方式显示
25         self.contentMode = UIViewContentModeScaleAspectFill;
26         // 剪除框外图形
27         self.clipsToBounds = YES;
28        
29         // 允许用户交互
30         self.userInteractionEnabled = YES;
31        
32         // gif logo
33         UIImageView *gifLogo = [[UIImageView alloc] initWithImage:[UIImage imageWithNamed:@"timeline_image_gif"]];
34         [self addSubview:gifLogo];
35         self.gifLogo = gifLogo;
36     }
37     return self;
38 }
39 
40 - (void)setPic:(HVWPic *)pic {
41     _pic = pic;
42    
43     // 显示配图到view上
44     [self setImageWithURL:[NSURL URLWithString:pic.thumbnail_pic] placeholderImage:[UIImage imageWithNamed:@"timeline_image_placeholder"]];
45    
46     // 如果是gif文件,需要加上标识
47     if ([pic.thumbnail_pic.pathExtension.lowercaseString isEqualToString:@"gif"]) {
48         self.gifLogo.hidden = NO;
49     } else {
50         self.gifLogo.hidden = YES;
51     }
52 }
53 
54 - (void)layoutSubviews {
55     [super layoutSubviews];
56    
57     if (self.gifLogo && self.gifLogo.hidden==NO) {
58         self.gifLogo.x = self.width - self.gifLogo.width;
59         self.gifLogo.y = self.height - self.gifLogo.height;
60     }
61 }
62 
63 @end
 
(3)创建一个配图区view类
 1 //
 2 //  HVWStatusPhotosView.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/2/28.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HVWStatusPhotosView : UIView
12 
13 /** 配图数组,里面装载的时HVWPic模型 */
14 @property(nonatomic, strong) NSArray *photos;
15 
16 /** 根据配图数量计算相册尺寸 */
17 + (CGSize) photosViewSizeWithCount:(int)count;
18 
19 @end
 
  1 //
  2 //  HVWStatusPhotosView.m
  3 //  HVWWeibo
  4 //
  5 //  Created by hellovoidworld on 15/2/28.
  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "HVWStatusPhotosView.h"
 10 #import "HVWStatusPhotoView.h"
 11 #import "UIImageView+WebCache.h"
 12 #import "HVWPhotoBrowser.h"
 13 
 14 #define HVWStatusPhotosTotalCount 9
 15 #define HVWStatusPhotosMaxCol(count) ((count==4)?2:3);
 16 #define HVWStatusPhotoWidth 70
 17 #define HVWStatusPhotoHeight HVWStatusPhotoWidth
 18 #define HVWStatusPhotoMargin 10
 19 
 20 @interface HVWStatusPhotosView()
 21 
 22 /** 相册内的配图view数组 */
 23 @property(nonatomic, strong) NSMutableArray *photoViews;
 24 
 25 /** 大图 */
 26 @property(nonatomic, weak) UIImageView *bigPhotoView;
 27 
 28 /** 被点击的小图frame */
 29 @property(nonatomic, assign) CGRect clickedSmallPhotoFrame;
 30 
 31 @end
 32 
 33 @implementation HVWStatusPhotosView
 34 
 35 - (NSMutableArray *)photoViews {
 36     if (nil == _photoViews) {
 37         _photoViews = [NSMutableArray array];
 38     }
 39     return _photoViews;
 40 }
 41 
 42 /** 使用代码初始化调用 */
 43 - (instancetype)initWithFrame:(CGRect)frame {
 44     self = [super initWithFrame:frame];
 45     if (self) {
 46         self.userInteractionEnabled = YES;
 47        
 48         // 先创建好n个配图view
 49         for (int i=0; i<HVWStatusPhotosTotalCount; i++) {
 50             HVWStatusPhotoView *photoView = [[HVWStatusPhotoView alloc] init];
 51             [self addSubview:photoView];
 52             [self.photoViews addObject:photoView];
 53            
 54             // 配置点击手势
 55             UITapGestureRecognizer *rec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapSamllPhoto:)];
 56             [photoView addGestureRecognizer:rec];
 57         }
 58     }
 59    
 60     return self;
 61 }
 62 
 63 /** 设置配图 */
 64 - (void)setPhotos:(NSArray *)photoUrls {
 65     _photos = photoUrls;
 66    
 67     // 配置所有配图子view
 68     for (int i=0; i<self.photoViews.count; i++) {
 69         HVWStatusPhotoView *photoView = self.photoViews[i];
 70         if (i < photoUrls.count) {
 71             photoView.pic =  photoUrls[i];
 72             photoView.tag = i;
 73             photoView.hidden = NO;
 74         } else {
 75             photoView.hidden = YES;
 76         }
 77     }
 78 }
 79 
 80 /** 布局子控件 */
 81 - (void)layoutSubviews {
 82     [super layoutSubviews];
 83    
 84     int photosCount = self.photos.count;
 85    
 86     // 布局所有配图
 87     for (int i=0; i<photosCount; i++) {
 88         HVWStatusPhotoView *photoView = self.photoViews[i];
 89         int row = i / HVWStatusPhotosMaxCol(photosCount); // 配图所在行数
 90         int col = i % HVWStatusPhotosMaxCol(photosCount); // 配图所在列数
 91        
 92         CGFloat photoX = col * (HVWStatusPhotoWidth + HVWStatusPhotoMargin);
 93         CGFloat photoY = row * (HVWStatusPhotoHeight + HVWStatusPhotoMargin);
 94         photoView.frame = CGRectMake(photoX, photoY, HVWStatusPhotoWidth, HVWStatusPhotoHeight);
 95     }
 96 }
 97 
 98 /** 根据配图数量计算相册尺寸 */
 99 + (CGSize) photosViewSizeWithCount:(int)count {
100     int maxCount = HVWStatusPhotosMaxCol(count);
101    
102     // 总列数
103     int totalCol = count > maxCount? maxCount : count;
104     // 总行数
105     int totalRow = (count + maxCount - 1) / maxCount;
106    
107     CGFloat width = totalCol * (HVWStatusPhotoWidth + HVWStatusPhotoMargin) - HVWStatusPhotoMargin;
108     CGFloat height = totalRow * (HVWStatusPhotoHeight + HVWStatusPhotoMargin) - HVWStatusPhotoMargin;
109     return CGSizeMake(width, height);
110 }
111 
112 /** 点击小图手势事件 */
113 - (void) tapSamllPhoto:(UITapGestureRecognizer *) rec {
114     // 创建一个全屏遮盖背景
115     UIView *bigPhotoCover = [[UIView alloc] init];
116     bigPhotoCover.frame = [UIScreen mainScreen].bounds;
117     bigPhotoCover.backgroundColor = [UIColor blackColor];
118    
119     // 添加点击遮盖手势
120     UITapGestureRecognizer *tapCoverRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapPhotoCover:)];
121     [bigPhotoCover addGestureRecognizer:tapCoverRec];
122    
123     // 添加到主窗口上
124     [[[UIApplication sharedApplication] keyWindow] addSubview:bigPhotoCover];
125    
126     // 被点击的小图
127     HVWStatusPhotoView *photoView = (HVWStatusPhotoView *)rec.view;
128    
129     // 创建一个要放大的图片,使用中等尺寸的配图
130     HVWPic *pic = self.photos[photoView.tag];
131     UIImageView *bigPhotoView = [[UIImageView alloc] init];
132     self.bigPhotoView = bigPhotoView;
133     bigPhotoView.contentMode = UIViewContentModeScaleAspectFill;
134     bigPhotoView.clipsToBounds = YES;
135    
136     // 下载图片
137     [bigPhotoView setImageWithURL:[NSURL URLWithString:pic.bmiddle_pic] placeholderImage:[UIImage imageWithNamed:@"timeline_image_placeholder"]];
138    
139     // 转换大图的frame坐标,从photosView坐标转换到遮盖view坐标
140     bigPhotoView.frame = [bigPhotoCover convertRect:photoView.frame fromView:self];
141     self.clickedSmallPhotoFrame = bigPhotoView.frame;
142    
143     // 添加到遮盖上
144     [bigPhotoCover addSubview:bigPhotoView];
145    
146     // 放大图片
147     [UIView animateWithDuration:0.5 animations:^{
148         bigPhotoView.contentMode = UIViewContentModeScaleAspectFit;
149         bigPhotoView.clipsToBounds = NO;
150         CGFloat bigPhotoWidth = bigPhotoCover.width;
151         CGFloat bigPhotoHeight = bigPhotoView.height * (bigPhotoWidth / bigPhotoView.width);
152         CGFloat bigPhotoX = 0;
153         CGFloat bigPhotoY = bigPhotoHeight>=HVWScreenHeight? 0 : (HVWScreenHeight - bigPhotoHeight) * 0.5;
154         bigPhotoView.frame = CGRectMake(bigPhotoX, bigPhotoY, bigPhotoWidth, bigPhotoHeight);
155     }];
156    
157 }
158 
159 /** 点击大图展示遮盖手势事件 */
160 - (void) tapPhotoCover:(UITapGestureRecognizer *) rec {
161     [UIView animateWithDuration:0.5 animations:^{
162         // 缩回图片
163         self.bigPhotoView.frame = self.clickedSmallPhotoFrame;
164     } completion:^(BOOL finished) {
165         // 消除遮盖
166         [rec.view removeFromSuperview];
167     }];
168 }
169 
170 @end
 
 
B.大配图浏览器
1.需求
  • 封装出一个大图浏览器,能够滚动浏览大图
  • 显示页码
 
PhotosBrowser
 
 
2.思路
  • 使用一个UIView,内部封装一个UIScrollView
  • 传入所有配图(中等图片)地址
  • 传入所有配图缩略图frame给浏览器,用作图片放大、缩回动画操作
  • 传入当前打开图片索引
 
微博界面的配图区:
Image(159)
 
配图浏览器层次结构:(显示中等图片)
  • 使用一个Scrollview装载作为滚动浏览容器
  • 使用两个自定义UIView作为遮盖cover
  • cover配有一个UIImageView成员,用来加载图片
  • 一个cover用于当前显示,另一个cover用于当滚动时(左边或右边)显示上一张或下一张配图
 
Image(160)
 
Image(161)
 
3.实现
(1)配图浏览器
 1 //
 2 //  HVWPhotoBrowser.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/3/1.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HVWPhotoBrowser : UIView
12 
13 /** 配图地址数组 */
14 @property(nonatomic, strong) NSMutableArray *photoUrls;
15 
16 /** 当前配图序号 */
17 @property(nonatomic, assign) int currentPhotoIndex;
18 
19 /** 配图组原始frame数组 */
20 @property(nonatomic, strong) NSArray *photoOriginalFrames;
21 
22 @end
 
  1 //
  2 //  HVWPhotoBrowser.m
  3 //  HVWWeibo
  4 //
  5 //  Created by hellovoidworld on 15/3/1.
  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "HVWPhotoBrowser.h"
 10 #import "UIImageView+WebCache.h"
 11 #import "SDWebImageManager.h"
 12 #import "HVWPhotoCover.h"
 13 #import "HVWPhotoPageLabel.h"
 14 
 15 @interface HVWPhotoBrowser() <UIScrollViewDelegate>
 16 
 17 /** 当前背景 */
 18 @property(nonatomic, weak) HVWPhotoCover *cover;
 19 /** 替换用背景 */
 20 @property(nonatomic, weak) HVWPhotoCover *backupCover;
 21 
 22 /** 滚动配图展示view */
 23 @property(nonatomic, weak) UIScrollView *photoScrollView;
 24 
 25 /** 上次滚动x位置 */
 26 @property(nonatomic, assign) CGFloat lastOffsetX;
 27 
 28 /** 是否正在滚动 */
 29 @property(nonatomic, assign, getter=isScrolling) BOOL scrolling;
 30 
 31 /** 是否已经运行了开场动画(放大) */
 32 @property(nonatomic, assign, getter=isDidRunAnimation) BOOL didRunAnimation;
 33 
 34 /** 页码 */
 35 @property(nonatomic, weak) HVWPhotoPageLabel *pageLabel;
 36 
 37 @end
 38 
 39 @implementation HVWPhotoBrowser
 40 
 41 /** 使用代码创建调用的初始化方法 */
 42 - (instancetype)initWithFrame:(CGRect)frame {
 43     self = [super initWithFrame:frame];
 44    
 45     if (self) {
 46         // 隐藏状态栏
 47         [UIApplication sharedApplication].statusBarHidden = YES;
 48        
 49         self.backgroundColor = [UIColor blackColor];
 50        
 51         // 滚动配图展示
 52         UIScrollView *photoScrollView = [[UIScrollView alloc] init];
 53         [self addSubview:photoScrollView];
 54         self.photoScrollView = photoScrollView;
 55         photoScrollView.delegate = self;
 56 
 57         photoScrollView.scrollEnabled = YES;
 58         photoScrollView.userInteractionEnabled = YES;
 59         photoScrollView.pagingEnabled = YES;
 60         photoScrollView.showsHorizontalScrollIndicator = NO;
 61         photoScrollView.showsVerticalScrollIndicator = YES;
 62        
 63         // 配图背景
 64         HVWPhotoCover *cover = [[HVWPhotoCover alloc] init];
 65         self.cover = cover;
 66         [photoScrollView addSubview:cover];
 67        
 68         HVWPhotoCover *backupCover = [[HVWPhotoCover alloc] init];
 69         self.backupCover = backupCover;
 70         [photoScrollView addSubview:backupCover];
 71        
 72         // 添加点击遮盖手势
 73         UITapGestureRecognizer *tapCoverRec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapPhotoCover:)];
 74         [self addGestureRecognizer:tapCoverRec];
 75        
 76         // 页码
 77         HVWPhotoPageLabel *pageLabel = [[HVWPhotoPageLabel alloc] init];
 78         [self addSubview: pageLabel];
 79         self.pageLabel = pageLabel;
 80     }
 81     return self;
 82 }
 83 
 84 - (void)layoutSubviews {
 85     [super layoutSubviews];
 86    
 87     // 图片滚动浏览器
 88     self.photoScrollView.frame = [UIScreen mainScreen].bounds;
 89    
 90     // 页码
 91     self.pageLabel.frame = (CGRect){{0, 10}, {self.width, 35}};
 92 }
 93 
 94 /**  配置当前配图 */
 95 - (void)setCurrentPhotoIndex:(int)currentPhotoIndex {
 96     _currentPhotoIndex = currentPhotoIndex;
 97    
 98     // 由于滚动结束触发此方法,不需要重新加载图片
 99     if (!self.isDidRunAnimation) {
100         // 加载图片
101         [self loadImage:self.cover withPhotoIndex:currentPhotoIndex];
102     }
103    
104     // 页码
105     [self.pageLabel changePageLabel:currentPhotoIndex];
106 }
107 
108 /** 点击大图展示遮盖手势事件 */
109 - (void) tapPhotoCover:(UITapGestureRecognizer *) rec {
110     [UIView animateWithDuration:0.5 animations:^{
111         // 缩回图片
112         UIImageView *photoView = self.cover.photoView;
113         photoView.frame = [self currentPhotoOriginalFrame];
114        
115         // 恢复状态栏显示
116         [UIApplication sharedApplication].statusBarHidden = NO;
117     } completion:^(BOOL finished) {
118         // 消除遮盖
119         [rec.view removeFromSuperview];
120     }];
121 }
122 
123 /** 所有配图 */
124 - (void)setPhotoUrls:(NSMutableArray *)photoUrls {
125     _photoUrls = photoUrls;
126    
127     // 配置scrollView
128     self.photoScrollView.contentSize = CGSizeMake(HVWScreenWidth * photoUrls.count, 0);
129    
130     // 配置cover
131     self.pageLabel.totalPageCount = photoUrls.count;
132 }
133 
134 #pragma mark - UIScrollViewDelegate
135 /** 拖曳中 */
136 - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
137     CGFloat offsetX = scrollView.contentOffset.x;
138    
139     if (!self.isScrolling) { // 是否正在滚动,仅需在滚动开始的一刻加载图片
140         if (offsetX > self.lastOffsetX) {
141             [self loadImage:self.backupCover withPhotoIndex:self.currentPhotoIndex + 1];
142             // 设置滚动标识
143             self.scrolling = YES;
144         } else if (offsetX < self.lastOffsetX) {
145             [self loadImage:self.backupCover withPhotoIndex:self.currentPhotoIndex - 1];
146             // 设置滚动标识
147             self.scrolling = YES;
148         }
149     }
150    
151     // 设置页码
152     int pageIndex =  (offsetX + self.photoScrollView.width * 0.5) / self.photoScrollView.width;
153     [self.pageLabel changePageLabel:pageIndex];
154 }
155 
156 /** 滚动完全停止 */
157 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
158     // 更新滚动位置
159     self.lastOffsetX = scrollView.contentOffset.x;
160    
161     // 当前页码
162     int currentPhotoIndex = self.lastOffsetX / HVWScreenWidth;
163     // 如果进行了换页
164     if (currentPhotoIndex != self.currentPhotoIndex) {
165         // 更新当前图片和替换图片
166         HVWPhotoCover *tempCover = self.backupCover;
167         self.backupCover = self.cover;
168         self.cover = tempCover;
169 
170         // 更新当前图片索引
171         self.currentPhotoIndex = currentPhotoIndex;
172     }
173    
174     // 重置滚动标识
175     self.scrolling = NO;
176 }
177 
178 /** 当前图片缩略图frame */
179 - (CGRect)currentPhotoOriginalFrame {
180     return [self.photoOriginalFrames[self.currentPhotoIndex] CGRectValue];
181 }
182 
183 /** 当前cover的frame */
184 - (CGRect)currentPhotoCoverFrame:(int)photoIndex {
185     return CGRectMake(photoIndex * HVWScreenWidth, 0, HVWScreenWidth, HVWScreenHeight);
186 }
187 
188 /** 加载配图 */
189 - (void) loadImage:(HVWPhotoCover *)cover withPhotoIndex:(int)photoIndex{
190     if (photoIndex < 0 || photoIndex >= self.photoUrls.count) return;
191    
192     // 取得配图地址
193     NSString *currentPhotoUrlStr = self.photoUrls[photoIndex];
194    
195     // 加入到显示区
196     cover.frame = [self currentPhotoCoverFrame:photoIndex];
197     UIImageView *photoView = cover.photoView;
198     photoView.frame = [self currentPhotoOriginalFrame];
199    
200     // 当前scrollView的offsetX
201     self.lastOffsetX = photoIndex * HVWScreenWidth;
202    
203     // 先设置一张占位图
204     [photoView setImage:[UIImage imageWithNamed:@"timeline_image_placeholder"]];
205    
206     // 放大图片
207     if (!self.isDidRunAnimation) { // 非滚动切换来的图片,需要进行放大动画
208         // 滚动到相应位置
209         [self.photoScrollView setContentOffset:CGPointMake(photoIndex * HVWScreenWidth, 0)];
210        
211         __weak UIImageView *tempPhotoView = photoView;
212         [UIView animateWithDuration:0.5 animations:^{
213            
214             CGFloat placeHolderWidth = self.width;
215             CGFloat placeHolderHeight = placeHolderWidth;
216             CGFloat placeHolderX = 0;
217             CGFloat placeHolderY = (HVWScreenHeight - placeHolderHeight) * 0.5;
218             tempPhotoView.frame = CGRectMake(placeHolderX, placeHolderY, placeHolderWidth, placeHolderHeight);
219            
220         } completion:^(BOOL finished) {
221             self.didRunAnimation = YES;
222             [self setupPhotoView:photoView withUrl:currentPhotoUrlStr];
223         }];
224     } else { // 滚动切换图片,直接加载
225         UIImageView *backupPhotoView = self.backupCover.photoView;
226         [backupPhotoView setImage:[UIImage imageWithNamed:@"timeline_image_placeholder"]];
227         CGFloat placeHolderWidth = self.width;
228         CGFloat placeHolderHeight = placeHolderWidth;
229         CGFloat placeHolderX = 0;
230         CGFloat placeHolderY = (HVWScreenHeight - placeHolderHeight) * 0.5;
231         backupPhotoView.frame = CGRectMake(placeHolderX, placeHolderY, placeHolderWidth, placeHolderHeight);
232        
233         [self setupPhotoView:photoView withUrl:currentPhotoUrlStr];
234     }
235 }
236 
237 /** 下载并设置图片 */
238 - (void) setupPhotoView:(UIImageView *)photoView withUrl:(NSString *)currentPhotoUrlStr {
239     // 下载图片
240     __weak UIImageView *tempPhotoView = photoView;
241     [photoView setImageWithURL:[NSURL URLWithString:currentPhotoUrlStr] placeholderImage:[UIImage imageWithNamed:@"timeline_image_placeholder"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
242         // 下载完毕,重新根据图片实际大小计算尺寸、位置
243         tempPhotoView.height = image.size.height * (tempPhotoView.width / image.size.width);
244         tempPhotoView.y = tempPhotoView.height>=HVWScreenHeight? 0 : (HVWScreenHeight - tempPhotoView.height) * 0.5;
245     }];
246 }
247 
248 @end
 
 
(2)遮盖cover
 1 //
 2 //  HVWPhotoCover.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/3/2.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HVWPhotoCover : UIView
12 
13 /** 配图 */
14 @property(nonatomic, weak) UIImageView *photoView;
15 
16 @end
 
 1 //
 2 //  HVWPhotoCover.m
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/3/2.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "HVWPhotoCover.h"
10 
11 @interface HVWPhotoCover()
12 
13 /** 页码 */
14 @property(nonatomic, weak) UILabel *pageLabel;
15 
16 @end
17 
18 @implementation HVWPhotoCover
19 
20 - (instancetype)initWithFrame:(CGRect)frame {
21     self = [super initWithFrame:frame];
22   
23     if (self) {
24         // 配图
25         UIImageView *photoView = [[UIImageView alloc] init];
26         photoView.contentMode = UIViewContentModeScaleAspectFill; // 填充图片
27         photoView.clipsToBounds = YES; // 剪除多余部分
28         self.photoView = photoView;
29         [self addSubview:photoView];
30     }
31     return self;
32 }
33 
34 @end
 
 
(3)页码
 1 //
 2 //  HVWPhotoPageLabel.h
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/3/3.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HVWPhotoPageLabel : UILabel
12 
13 /** 总页数 */
14 @property(nonatomic, assign) int totalPageCount;
15 
16 /** 改变页码 */
17 - (void)changePageLabel:(int)pageIndex;
18 
19 @end
 
 1 //
 2 //  HVWPhotoPageLabel.m
 3 //  HVWWeibo
 4 //
 5 //  Created by hellovoidworld on 15/3/3.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "HVWPhotoPageLabel.h"
10 
11 @implementation HVWPhotoPageLabel
12 
13 - (instancetype)initWithFrame:(CGRect)frame {
14     self = [super initWithFrame:frame];
15    
16     if (self) {
17         self.font = [UIFont systemFontOfSize:20];
18         self.textAlignment = NSTextAlignmentCenter;
19         self.textColor = [UIColor whiteColor];
20     }
21     return self;
22 }
23 
24 /** 改变页码 */
25 - (void)changePageLabel:(int)pageIndex {
26     self.text = [NSString stringWithFormat:@"%d/%d", pageIndex + 1, self.totalPageCount];
27 }
28 
29 @end
 
(4)在微博配图区点击缩略图
  1 //
  2 //  HVWStatusPhotosView.m
  3 //  HVWWeibo
  4 //
  5 //  Created by hellovoidworld on 15/2/28.
  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "HVWStatusPhotosView.h"
 10 #import "HVWStatusPhotoView.h"
 11 #import "UIImageView+WebCache.h"
 12 #import "HVWPhotoBrowser.h"
 13 
 14 #define HVWStatusPhotosTotalCount 9
 15 #define HVWStatusPhotosMaxCol(count) ((count==4)?2:3);
 16 #define HVWStatusPhotoWidth 70
 17 #define HVWStatusPhotoHeight HVWStatusPhotoWidth
 18 #define HVWStatusPhotoMargin 10
 19 
 20 @interface HVWStatusPhotosView()
 21 
 22 /** 相册内的配图view数组 */
 23 @property(nonatomic, strong) NSMutableArray *photoViews;
 24 
 25 /** 大图 */
 26 @property(nonatomic, weak) UIImageView *bigPhotoView;
 27 
 28 /** 被点击的小图frame */
 29 @property(nonatomic, assign) CGRect clickedSmallPhotoFrame;
 30 
 31 @end
 32 
 33 @implementation HVWStatusPhotosView
 34 
 35 - (NSMutableArray *)photoViews {
 36     if (nil == _photoViews) {
 37         _photoViews = [NSMutableArray array];
 38     }
 39     return _photoViews;
 40 }
 41 
 42 /** 使用代码初始化调用 */
 43 - (instancetype)initWithFrame:(CGRect)frame {
 44     self = [super initWithFrame:frame];
 45     if (self) {
 46         self.userInteractionEnabled = YES;
 47        
 48         // 先创建好n个配图view
 49         for (int i=0; i<HVWStatusPhotosTotalCount; i++) {
 50             HVWStatusPhotoView *photoView = [[HVWStatusPhotoView alloc] init];
 51             [self addSubview:photoView];
 52             [self.photoViews addObject:photoView];
 53            
 54             // 配置点击手势
 55             UITapGestureRecognizer *rec = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapSamllPhoto:)];
 56             [photoView addGestureRecognizer:rec];
 57         }
 58     }
 59    
 60     return self;
 61 }
 62 
 63 /** 设置配图 */
 64 - (void)setPhotos:(NSArray *)photoUrls {
 65     _photos = photoUrls;
 66    
 67     // 配置所有配图子view
 68     for (int i=0; i<self.photoViews.count; i++) {
 69         HVWStatusPhotoView *photoView = self.photoViews[i];
 70         if (i < photoUrls.count) {
 71             photoView.pic =  photoUrls[i];
 72             photoView.tag = i;
 73             photoView.hidden = NO;
 74         } else {
 75             photoView.hidden = YES;
 76         }
 77     }
 78 }
 79 
 80 /** 布局子控件 */
 81 - (void)layoutSubviews {
 82     [super layoutSubviews];
 83    
 84     int photosCount = self.photos.count;
 85    
 86     // 布局所有配图
 87     for (int i=0; i<photosCount; i++) {
 88         HVWStatusPhotoView *photoView = self.photoViews[i];
 89         photoView.contentMode = UIViewContentModeScaleAspectFill;
 90         photoView.clipsToBounds = YES;
 91        
 92         int row = i / HVWStatusPhotosMaxCol(photosCount); // 配图所在行数
 93         int col = i % HVWStatusPhotosMaxCol(photosCount); // 配图所在列数
 94        
 95         CGFloat photoX = col * (HVWStatusPhotoWidth + HVWStatusPhotoMargin);
 96         CGFloat photoY = row * (HVWStatusPhotoHeight + HVWStatusPhotoMargin);
 97         photoView.frame = CGRectMake(photoX, photoY, HVWStatusPhotoWidth, HVWStatusPhotoHeight);
 98     }
 99    
100 }
101 
102 /** 根据配图数量计算相册尺寸 */
103 + (CGSize) photosViewSizeWithCount:(int)count {
104     int maxCount = HVWStatusPhotosMaxCol(count);
105    
106     // 总列数
107     int totalCol = count > maxCount? maxCount : count;
108     // 总行数
109     int totalRow = (count + maxCount - 1) / maxCount;
110    
111     CGFloat width = totalCol * (HVWStatusPhotoWidth + HVWStatusPhotoMargin) - HVWStatusPhotoMargin;
112     CGFloat height = totalRow * (HVWStatusPhotoHeight + HVWStatusPhotoMargin) - HVWStatusPhotoMargin;
113     return CGSizeMake(width, height);
114 }
115 
116 /** 点击小图手势事件 */
117 - (void) tapSamllPhoto:(UITapGestureRecognizer *) rec {
118     // 创建一个全屏遮盖背景
119     HVWPhotoBrowser *photoBrowser = [[HVWPhotoBrowser alloc] init];
120     photoBrowser.frame = [UIScreen mainScreen].bounds;
121    
122     // 添加到主窗口上
123     // 一定要先添加到主窗口上,再进行坐标转换!!!否则会得到增大一倍的frame!!!
124     [[[UIApplication sharedApplication] keyWindow] addSubview:photoBrowser];
125    
126     // 输入点击图片坐标
127     HVWStatusPhotoView *smallPhotoView = (HVWStatusPhotoView *)rec.view;
128     photoBrowser.photoOriginalFrames = [self photoOriginalFramesInView:photoBrowser];
129    
130     // 配置配图url
131     NSMutableArray *photoUrls = [NSMutableArray array];
132     for(HVWPic *pic in self.photos) {
133         [photoUrls addObject:pic.bmiddle_pic];
134     }
135     photoBrowser.photoUrls = photoUrls;
136     photoBrowser.currentPhotoIndex = smallPhotoView.tag;
137 }
138 
139 /** 所有缩略图的frame */
140 - (NSArray *) photoOriginalFramesInView:(UIView *)view {
141     NSMutableArray *photoOriginalFrames = [NSMutableArray array];
142     for (HVWStatusPhotoView *photoView in self.photoViews) {
143         CGRect convertFrame = [view convertRect:photoView.frame fromView:self];
144         [photoOriginalFrames addObject:[NSValue valueWithCGRect:convertFrame]];
145     }
146     return photoOriginalFrames;
147 }
148  
149 
150 @end
 
原文地址:https://www.cnblogs.com/hellovoidworld/p/4311092.html