一 功能图
二 讲解思路
1 回顾上一篇内容
2 创建加载图片类(同时创建xib)
3 点击图片查看大图
4 点击查看大图(查看长图)
5 model出展示图片的控制器
6 保存图片
7 封装根据网络状态展示不同的图片
三 回顾上一篇内容
1 上一篇内容讲到对整个cell的分析,通过创建一个类(XIB)来管理cell的顶部和尾部总共九个控件.然后创建三个不同的类(xib),各自负责自己的中间部分,然后根据服务器返回的帖子类型,拼接上对应的cell,展示在用户眼前.
四 处理图片
1 处理原因: 由于从服务器中返回的图片的类型有两种:小图和长图,相对于其他部分,图片的处理相对来说比较麻烦.所以这里我先将展示图片的功能处理下.
2 创建加载图片类
3 处理图片的xib
—-> 3.1 注意一 : 占位文字”百思不得姐”字样的放置位置,放在UIImageView的下面,有利于在图片还没有从服务器中加载的时候,能显示”百思不得姐”字样,给用户比较好的体验(由于美工没有提供占位视图,只提供了一段文字,注意设置文字的样式为:下图)
—-> 3.2 注意二 : 注意”点击查看大图”按钮中的图片和文字中间的距离.我们是通过让图片向左移动5厘米并且让文字想右移动5厘米来达到中间的间隙,并且能让图片和文字总体处于中间位置.(设置地方)
—> 图一 :
—> 图二 :
4 图片类中需要用到的属性(通过拖线的方式拿到xib中需要的属性)
/**
* 背景图片
*/
@property (weak, nonatomic) IBOutlet UIImageView *pictureBackImageView;
/**
* 点击查看大图
*/
@property (weak, nonatomic) IBOutlet UIButton *seeBigPictureImageView;
/**
* 动图
*/
@property (weak, nonatomic) IBOutlet UIImageView *gifImageView;
5 定义模型属性(用于重写模型属性的set方法)
/**
* 导入模型
*/
@property (nonatomic, strong) XFJItem *topicesPicture;
6 模型的set方法
—-> 6.1 开启上下文(如果图片为长图)
—-> 6.2 绘图(如果图片为长图)
—-> 6.3 关闭上下文 (如果图片为长图)
总体代码:
#pragma mark - 模型属性的set方法
- (void )setTopicesPicture:(XFJItem *)topicesPicture
{
_topicesPicture = topicesPicture;
[self .pictureBackImageView XFJ_originalImageURL:topicesPicture.image1 thumbnailImageURL:topicesPicture.image0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image == nil ) return ;
if (!topicesPicture.isBigPicture ) return ;
CGFloat pictureW = topicesPicture.middleFrame .size .width ;
CGFloat pictureH = topicesPicture.middleFrame .size .height ;
UIGraphicsBeginImageContext(CGSizeMake(pictureW, pictureH));
[image drawInRect:CGRectMake(0 , 0 , pictureW, pictureW * topicesPicture.height / topicesPicture.width )];
self .pictureBackImageView .image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}];
self .seeBigPictureImageView .hidden = !topicesPicture.isBigPicture ;
self .gifImageView .hidden = !topicesPicture.is_gif ;
}
五 处理点击图片和查看大图业务逻辑
1 点击查看大图(通过拖线的方式我们进行对按钮的监听)
- (IBAction )seeBigPictureClick
{
[self seeBigPicture];
}
2 调用的方法
#pragma mark - 实现轻按事件
- (void )seeBigPicture
{
XFJSeeBigPicture *seePicture = [[XFJSeeBigPicture alloc] init];
seePicture.topicesItem = self .topicesPicture ;
[self .window .rootViewController presentViewController:seePicture animated:YES completion:nil ];
}
3 由于当用户不管点击图片还是点击查看大图都会使得图片上展示出来,所以,我们给图片添加一个点按手势,其中点按要实现的方法恰好是查看大图的方法.
#pragma mark - 加载xib的时候回来到这个方法
- (void )awakeFromNib
{
self .pictureBackImageView .userInteractionEnabled = YES ;
UITapGestureRecognizer *gest = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector (seeBigPicture)];
[self .pictureBackImageView addGestureRecognizer:gest];
}
六 展示图片的控制器(处理)
1 通过点击图片或者查看图片的按钮,可以看得出控制器是直接model出来的.
3 展示的xib效果图
4 需要用到的属性
/**
* 保存按钮
*/
@property (weak, nonatomic) IBOutlet UIButton *saveButton;
@property (nonatomic, weak) UIImageView *imageView;
5 通过直接拖线的方式,处理返回按钮(将model出来的控制器dissmiss)
- (IBAction )backClick
{
[self dismissViewControllerAnimated:YES completion:nil ];
}
#pragma mark - 添加scrollerView
- (void )setUpContentView
{
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.frame = CGRectMake(0 , 0 , XFJ_screenW, XFJ_screenH);
[scrollView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector (backClick)]];
scrollView.backgroundColor = [UIColor blackColor];
[self .view insertSubview:scrollView atIndex:0 ];
[self setUpcontentImageView:scrollView];
}
—-> 7.1 计算图片的高度
—-> 7.2 给图片添加一个缩放功能
总体的代码:
#pragma mark - 在contentView中添加UIImageView
- (void )setUpcontentImageView:(UIScrollView *)scrollView
{
UIImageView *imageView = [[UIImageView alloc] init];
[imageView sd_setImageWithURL:[NSURL URLWithString:self .topicesItem .image1 ] placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image == nil ) return ;
self .saveButton .enabled = YES ;
}];
imageView.XFJ_X = 0 ;
imageView.XFJ_Width = scrollView.XFJ_Width ;
[scrollView addSubview:imageView];
self .imageView = imageView;
imageView.XFJ_Height = imageView.XFJ_Width * self .topicesItem .height / self .topicesItem .width ;
if (imageView.XFJ_Height >= XFJ_screenH) {
imageView.XFJ_Y = 0 ;
scrollView.contentSize = CGSizeMake(0 , imageView.XFJ_Height );
}else {
imageView.XFJ_centerY = scrollView.XFJ_Height * 0.5 ;
}
CGFloat maxScale = self .topicesItem .width / self .imageView .XFJ_Width ;
if (maxScale >= 1.0 ) {
scrollView.maximumZoomScale = maxScale;
scrollView.delegate = self ;
}
}
8 代理方法处理缩放图片
#pragma mark - 代理方法
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self .imageView ;
}
9 保存图片
—-> 9.1 点击保存按钮,保存图片
- (IBAction )savePicture
{
UIImageWriteToSavedPhotosAlbum(self .imageView .image , self , @selector (image: didFinishSavingWithError: contextInfo:), nil );
}
—-> 9.2 提示用户是否保存成功
#pragma mark - 是否保存成功
- (void )image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
[SVProgressHUD showErrorWithStatus:@"保存失败" ];
}else {
[SVProgressHUD showSuccessWithStatus:@"保存成功" ];
}
}
—-> 9.3 注意 :UIImageWriteToSavedPhotosAlbum对该方法,苹果官方文档中有说明,@selector中调用的方法,必须是(下面)方法,否则就会报错.
// - (void )image :(UIImage *)image didFinishSavingWithError :(NSError *)error contextInfo :(void *)contextInfo;
七 建立联系
1 怎么样将各部分负责的UIView插入到自定义的cell中呢?
—-> 解答:通过下面的判断(self.topicesPicture.topicesPicture = topices;)主要作用
switch (self .topices .type ) {
case XFJTopicTypeWord:
self .topicesPicture .hidden = YES ;
self .topicesVideo .hidden = YES ;
self .topicesVoice .hidden = YES ;
break ;
case XFJTopicTypePicture:
self .topicesVideo .hidden = YES ;
self .topicesVoice .hidden = YES ;
self .topicesPicture .topicesPicture = topices;
self .topicesPicture .hidden = NO ;
break ;
case XFJTopicTypeVideo:
self .topicesPicture .hidden = YES ;
self .topicesVoice .hidden = YES ;
self .topicesVideo .topicesVideo = topices;
self .topicesVideo .hidden = NO ;
break ;
case XFJTopicTypeVoice:
self .topicesPicture .hidden =YES ;
self .topicesVoice .topicesVoice = topices;
self .topicesVoice .hidden = NO ;
self .topicesVideo .hidden = YES ;
break ;
default :
break ;
}
2 通过(self.topicesPicture.topicesPicture = topices;)需要加载对应的xib
- (XFJTopicesPictureView *)topicesPicture
{
if (_topicesPicture == nil ) {
// 创建xib
XFJTopicesPictureView *picture = [XFJTopicesPictureView XFJ_middleXib ];
// 添加到tableView中的contentView中
[self .contentView addSubview: picture];
// 赋值
_topicesPicture = picture;
}
return _topicesPicture;
}
3 调用下面的方法来加载对应的xib(self:谁调用就代表加载谁的xib)
#pragma mark - 实现快速创建xib的方法
+ (instancetype)XFJ_middleXib
{
return [[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self ) owner:nil options:nil ].firstObject ;
}
八 根据用户网络状态来下载不同规格的图片大小(封装)
1 思路:见下面伪代码
/*
if (缓存中有原图) {
self .imageView.image = 原图;
} else {
if (Wifi 环境) {
下载显示原图
} else if (手机自带网络) {
if (用户设置3 G\4 G环境下仍然下载原图) {
下载显示原图
} else {
下载显示小图
}
} else {
if (缓存中有小图) {
self .imageView.image = 小图;
} else {
self .imageView.image = 占位图片;
}
}
}*/
2 封装
—-> 2.1 .h文件
/**
* 设置下载的图片类型(原图或缩略图)
*
* @param originalImageURL 原图的URL
* @param thumbnailImageURL 缩略图的URL
* @param placeholderImage 占位视图
* @param completedBlock 设置完图片回调
*/
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage completed:(SDWebImageCompletionBlock)completedBlock;
/**
* 设置下载的图片类型(原图或缩略图)
*
* @param originalImageURL 原图的URL
* @param thumbnailImageURL 缩略图的URL
*/
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL;
/**
* 设置下载的图片类型(原图或缩略图)
*
* @param originalImageURL 原图的URL
* @param thumbnailImageURL 缩略图的URL
* @param placeholderImage 占位视图
*/
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage;
/**
* 设置下载的图片类型(原图或缩略图)
*
* @param originalImageURL 原图的URL
* @param thumbnailImageURL 缩略图的URL
* @param completedBlock 设置完图片回调
*/
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL completed:(SDWebImageCompletionBlock)completedBlock;
—-> 2.2 .m文件(需要导入的框架AFN)
#pragma mark - 不需要传占位视图和完成需要做的事
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL
{
[self XFJ_originalImageURL:originalImageURL thumbnailImageURL:thumbnailImageURL placeholderImage:nil completed:nil ];
}
#pragma mark - 需要传入占位视图
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage
{
[self XFJ_originalImageURL:originalImageURL thumbnailImageURL:thumbnailImageURL placeholderImage:placeholderImage completed:nil ];
}
#pragma mark - 需要设置完图片回调
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL completed:(SDWebImageCompletionBlock)completedBlock
{
[self XFJ_originalImageURL:originalImageURL thumbnailImageURL:thumbnailImageURL placeholderImage:nil completed:completedBlock];
}
#pragma mark - 需要设置占位视图和完成回调
- (void )XFJ_originalImageURL:(NSString *)originalImageURL thumbnailImageURL:(NSString *)thumbnailImageURL placeholderImage:(UIImage *)placeholderImage completed:(SDWebImageCompletionBlock)completedBlock
{
UIImage *originalImageView = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:originalImageURL];
if (originalImageView) {
[self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
}else {
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
if (manager.isReachableViaWiFi ) {
[self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
}else if (manager.isReachableViaWWAN ){
BOOL alwaysDownloadOriginalImage = [[NSUserDefaults standardUserDefaults] boolForKey:@"alwaysDownloadOriginalImage" ];
if (alwaysDownloadOriginalImage) {
[self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
}else {
[self sd_setImageWithURL:[NSURL URLWithString:thumbnailImageURL] placeholderImage:placeholderImage completed:completedBlock];
}
}else {
UIImage *thumbnailImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:thumbnailImageURL];
if (thumbnailImage) {
[self sd_setImageWithURL:[NSURL URLWithString:thumbnailImageURL] placeholderImage:placeholderImage completed:completedBlock];
}else {
[self sd_setImageWithURL:nil placeholderImage:placeholderImage completed:completedBlock];
}
}
}
}
九 总结
1 该部分着重的讲解了对图片处理和对用户网络状态显示多大规格的图片进行处理.代码内部的业务逻辑相对来说比较难(需要考虑到多方面的因素),但总的来说还是可以解决的,可能里面有一些还没有想到,后期想到会完善的.
2 后面我会继续完善百思不得姐,希望带给大家更多的不一样的想法,最后大家如果觉得我写的博客还满意的话,麻烦大家多多建议,多多关注我的官方博客,谢谢!!!!