[iOS微博项目 - 4.6] - 微博配图
A.微博配图
1.需求
- 显示原创微博、转发微博的缩略图
- 4张图使用2x2布局,其他使用3x3布局,最多9张
- 点击小图放大图片,下载中等图片并显示,使用动画转换
- 如果是gif文件,在缩略图上加上"gif"标识
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.需求
- 封装出一个大图浏览器,能够滚动浏览大图
- 显示页码
2.思路
- 使用一个UIView,内部封装一个UIScrollView
- 传入所有配图(中等图片)地址
- 传入所有配图缩略图frame给浏览器,用作图片放大、缩回动画操作
- 传入当前打开图片索引
微博界面的配图区:
配图浏览器层次结构:(显示中等图片)
- 使用一个Scrollview装载作为滚动浏览容器
- 使用两个自定义UIView作为遮盖cover
- cover配有一个UIImageView成员,用来加载图片
- 一个cover用于当前显示,另一个cover用于当滚动时(左边或右边)显示上一张或下一张配图
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