百思不得姐之图片处理(保存与下载)

2023-05-16

一 功能图

这里写图片描述

二 讲解思路

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];
    //如果不写这一句的话,会出现NaN的情况
    seePicture.topicesItem = self.topicesPicture;
    //model出该控制器
    [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出来的.

2 通过整体的图片在该控制器中的展示,我们不难看出,当图片为长图的时候用户需要往上滑动才能查看下面的图片,所以在dodel出来的控制器中层次结构为: UIScrollView–>UIImageView–>返回和保存按钮.

3 展示的xib效果图

这里写图片描述

4 需要用到的属性

/**
 *  保存按钮
 */
@property (weak, nonatomic) IBOutlet UIButton *saveButton;

@property (nonatomic, weak) UIImageView *imageView;

5 通过直接拖线的方式,处理返回按钮(将model出来的控制器dissmiss)

- (IBAction)backClick
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

6 添加UIScrollView

#pragma mark - 添加scrollerView
- (void)setUpContentView
{
    //创建UIScrollView
    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];
    //添加插入到view中
    [self.view insertSubview:scrollView atIndex:0];
    //调用方法
    [self setUpcontentImageView:scrollView];
}
—-> 6.1 注意 :创建的UIScrollView一定要选择插入到model出来的控制器中,否则会出错.不能直接添加.

7 添加UIScrollView上的UIImageView

—-> 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 - 代理方法
//return a view that will be scaled. if delegate returns nil, nothing happens
- (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

#pragma mark - 图片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 (用户设置3G\4G环境下仍然下载原图) {
                下载显示原图
            } 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) {//如果是wifi
            [self sd_setImageWithURL:[NSURL URLWithString:originalImageURL] placeholderImage:placeholderImage completed:completedBlock];
        }else if(manager.isReachableViaWWAN){//如果是3G或4G的话就看用户选择
            //从沙盒中读取用户对是否下载原图的配置
            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 后面我会继续完善百思不得姐,希望带给大家更多的不一样的想法,最后大家如果觉得我写的博客还满意的话,麻烦大家多多建议,多多关注我的官方博客,谢谢!!!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

百思不得姐之图片处理(保存与下载) 的相关文章

  • 解决 413 Request Entity Too Large(请求实体太大)

    今天做上传视频 xff0c 报错413 Request Entity Too Large 我们可以看到请求的body的大小 xff0c 在Content Length后显示 xff0c Nginx默认的request body为1M xff
  • Netty本身的编码解码的机制和问题分析

  • Protobuf基本介绍和使用

  • TCP粘包和拆包基本介绍

  • 我的大一学习生活总结

    今天最后的一科英语考完了 xff0c 但此刻的我并不觉的轻松 xff0c 我知道从现在开始就标志着我的大一已经结束了 xff0c 在大学仅有的四年时光就过去了四分之一 回想起大一这一年 xff0c 自问一下我到底学到了什么 xff1f 我发
  • 一个程序员的一生

    一个程序员的一生 作者 佚名 我在程序员的时候 xff0c 我一开始追逐这个API怎么用 xff0c 数据库SQL怎么写更优化 xff0c Dcom技术的细节 xff0c 然后我发现我写出来的产品为了符合客户 需求必须要大量修改 xff0c
  • E: Package ‘cmake‘ has no installation candidate

    在ubuntu中使用 sudo apt get install cmake 报错 xff1a E Package 39 cmake 39 has no installation candidate 解决方法 xff1a sudo apt g
  • 函数程序设计实验五:打印购物小票

    module HaskellStore where import Text Printf type Items 61 Item type Item 61 Name Amount Price type Name 61 String type
  • CSS实战——百度搜索首页

    成果 支持搜索内容 步骤 一般来说 xff1a 使用css 43 div进行页面的布局 xff0c css一般是用外联进行开发使用html进行每一个页面的填充 注意事项 id的命名规范 xff1a 父标签id 自己的idcss一般一个选择器
  • UNIX环境高级编程

    环境配置 1 下载apue 3e文件夹 xff0c 可以通过http www apuebook com code3e html现在源码 2 解压后执行进入apue 3e中执行make指令 如果出现 96 96 96 collect2 err
  • 常见的亮灭屏流程分析

    一 亮屏主要关键log 驱动按键时间 lt 3 gt 14082 058160 0 70 pmic thread kpd Power Key generate pressed 61 1 上层按键时间 09 25 15 13 07 19666
  • 冒烟测试和回归测试的区别

    每次新的版本出来的时候 xff0c 老大就让我们 冒烟 虽然不知道冒烟测试的含义 xff0c 但由于没有给用例 xff0c 我就随便跑跑 跑完冒烟后 xff0c 老大就让做 回归测试 xff0c 把bug回归掉 但是其实对2个概念还是不太理
  • 老旧电脑在虚拟机安装ubuntu运行环境的步骤及注意事项

    花了一天的时间在我的老电脑上用虚拟机装上了ubuntu xff0c 多灾多难 xff0c 记录一下问题和注意事项 老电脑的配置 xff1a cpu xff1a Intel Core TM 2 Duo CPU E7500 64 2 93GHz
  • x11vnc

    x11vnc display 0 auth guess rfbport 5900 forever shared noxdamage noncache repeat amp auth 关窗口退出 auth guess 关窗口不退出 用户注销退
  • 多个生产者和消费者线程

    span class token comment 作者 xff1a kuma 版本 xff1a v1 0 span span class token keyword public span span class token keyword
  • C/C++ 开源库及示例代码

    C C 43 43 开源库及示例代码 说明 本页面汇总俺收集的各种 C 和 C 43 43 的开源代码库 xff0c 不定期更新 如果你发现本页面的开源库有错漏之处 xff0c 非常欢迎给俺提供反馈 有 GitHub 帐号的同学 xff0c
  • UEFI分区的重建办法,不需要额外软件

    如果你的EFI分区还在 只是被破坏需要修复的话 xff0c 执行 bcdboot c windows l cn zh 即可 xff0c c是Windows安装的盘符 xff0c 如果是装机工具启动可能window的分区不是显示的c 如果连E
  • powershell 设置环境变量

    cmd 是用set 导出变量 xff0c 到了powershell中不好使了 xff0c 下面介绍下导出变量的方法 xff0c 比如想设置 ETCDCTL API 61 3 在powershell中执行下面命令就可以了 Env ETCDCT
  • Httpd 服务

    httpd服务 1 httpd服务简介 Apache HTTP Server xff08 简称Apache或httpd xff09 是Apache软件基金会的一个开放源代码的网页服务器软件 xff0c 旨在为unix xff0c windo
  • Lottie—json文件解析

    Lottie主要类图 xff1a Lottie对外通过控件LottieAnimationView暴露接口 xff0c 控制动画 LottieAnimationView继承自ImageView xff0c 通过当前时间绘制canvas显示到界

随机推荐