最近重新开始练习iOS开发,找感觉。

先做个简单的图片浏览选择功能。不用管是难还是简单,先实现一下。


一、步骤概述

包含三个步骤:

  • 创建页面:图片选择页(collectionView),图片预览页
  • 处理数据:在页面间传递图片数据集或者单张图片,用系统的Photo库API获取图片
  • 实现动画:各个手势(GestureRecognizer)结合数值的计算

练习重点:

  • 各种手势(GestureRecognizer)的运用

二、具体实现

创建页面

首先是创建相应的页面。这个作为最基础的部分还是在此略过。总共有三个页面:

  • 入口页
  • 选择页
  • 预览页
  • 选择图片后的入口页

处理数据

然后是处理图片数据,在页面间传递图片数据。

给图片加上点击事件,由于UIImageView默认不能交互,所以需要把交互打开:

在入口页导入系统的<Photos/Photos.h>库,在图片的点击事件响应方法里,调用Photo库“查看是否有权限”的API:

if (status == PHAuthorizationStatusNotDetermined) {[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {if (status == PHAuthorizationStatusAuthorized) {     // 有权限读取照片[self performLoadPhotoAssets]; // 自定义方法}}];
} else if (status == PHAuthorizationStatusAuthorized) {// 有权限读取照片[self performLoadPhotoAssets]; // 自定义方法
}
复制代码

当判断到有权限查看相册时,则执行获取图片的方法[self performLoadPhotoAssets]

  • 先从系统相册获取图片assetsArray
NSMutableArray *assetsArray = [NSMutableArray array];PHFetchOptions *options = [[PHFetchOptions alloc] init];
options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];PHFetchResult *fetchResult = [PHAsset fetchAssetsWithOptions:options];[fetchResult enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {[assetsArray addObject:obj];
}];
复制代码
  • 然后传递到下一个UICollectionView界面
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];layout.itemSize = CGSizeMake(100, 100);CGFloat space = (self.view.bounds.size.width - (4 * 100)) / 5;
if (space < 5) space = 5;
layout.minimumInteritemSpacing = space;layout.minimumLineSpacing = 15;layout.sectionInset = UIEdgeInsetsMake(15, space, 15, space);YLPhotoSelectionViewController *photoVC = [[YLPhotoSelectionViewController alloc] initWithCollectionViewLayout:layout];
photoVC.assetsArray = [assetsArray copy];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:photoVC];
[self presentViewController:nav animated:YES completion:nil];
复制代码

在这个UICollectionView界面,也就是图片选择页,在接口处自然是定义好属性:

@interface YLPhotoSelectionViewController : UICollectionViewController@property(nonatomic, copy)  NSArray * _Nullable assetsArray;@end
复制代码

这个collectionView没什么好多说的,实现collectionView的dataSource和delegate即可,唯一要注意的是在CollectionViewCell里继续引入并调用Photo库解码PHAseet:

  • cell里接受数据的属性
@interface YLPhotoCollectionViewCell : UICollectionViewCell@property(nonatomic, strong) PHAsset *asset;@end
复制代码
  • asset属性的set里解码PHAsset
- (void)setAsset:(PHAsset *)asset {__weak __typeof(self) weakSelf = self;[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:self.photoImageView.bounds.size contentMode:PHImageContentModeAspectFill options:NULL resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {if (result) {// 给cell里的图片视图ImageView赋值weakSelf.photoImageView.image = result;}}];}
复制代码

然后接着在collectionView的点击代理里,把整个图片数组和被选择图片的索引值传递给图片预览页:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {NSInteger row = indexPath.row;// 图片预览页YLPhotoPreviewViewController *previewVC = [[YLPhotoPreviewViewController alloc] init];// 传递图片和图片的索引值previewVC.photoAssetsArray = self.assetsArray;previewVC.photoIndex = row;[self.navigationController pushViewController:previewVC animated:YES];
}
复制代码

传递整个图片数组和被选择图片的索引值,而不是只传递被选择的图片,这样做目的是给轻扫手势切换图片提供相应的数据,通过对索引值的加和减来实现。

同样地,在图片预览页面的接口定义接收数据的属性:

@interface YLPhotoPreviewViewController : UIViewController@property(nonatomic, copy) NSArray  * _Nullable photoAssetsArray;
@property(nonatomic, assign) NSInteger photoIndex;@end
复制代码

图片的呈现很简单,一张铺满屏幕的UIImageView,同样用在cell里的Photo库的解码方法,把数据赋值给UIImageView,注意这里的图片是通过传递过来的两个属性组合取出:

PHAsset *asset = self.photoAssetsArray[self.photoIndex];
复制代码

实现动画

最后是这次的重点,实现各种手势操作:

  • 长按,UILongPressGestureRecognizer
  • 轻扫,UISwipeGestureRecognizer
  • 缩放,UIPinchGestureRecognizer
  • 旋转,UIRotationGestureRecognizer
  • 滑动,UIPanGestureRecognizer
  • 屏幕边缘滑动,UIScreenEdgePanGestureRecognizer

这里重点记录一下缩放、旋转和平移这三个手势实现时,都需要有处理的数据,全部代码在GitHub里。

首先它们都需要记录一个最终数值:

// 最终照片的比例
@property (assign, nonatomic) CGFloat finalPinchScale;
// 最终旋转角度
@property (assign, nonatomic) CGFloat finalRotaionAngle;
// 最终平移的位置
@property (assign, nonatomic) CGPoint finalPanTranslastion;
复制代码

其次都需要记录上次缩放、旋转或平移的值:

// 上次缩放的比例
static CGFloat _lastPinchScale = 1; // 上一次旋转的角度
static CGFloat _lastRotaionAngle = 0; // 上次平移的位置
static CGPoint _lastTranslation = {.x = 0, .y = 0};
复制代码

然后是根据操作的状态state来计算数值,以缩放的代码为例:

if (sender.state == UIGestureRecognizerStateChanged) {// 改变照片的缩放比例self.finalPinchScale = _lastPinchScale * currentPinchScale;// 将finalPinchScaley应用在照片上[self transformForImage]; // 自定义方法} else if (sender.state == UIGestureRecognizerStateEnded) {// 更新lastPinchScale的数值到本次缩放的比例_lastPinchScale = _lastPinchScale *currentPinchScale;}
复制代码

然后就是执行关键的自定义方法[self transformForImage]

- (void)transformForImage {// 把最终值传入相应的transform类型CGAffineTransform scaleTransform = CGAffineTransformMakeScale(self.finalPinchScale, self.finalPinchScale);CGAffineTransform rotationTransform = CGAffineTransformRotate(scaleTransform, self.finalRotaionAngle);CGAffineTransform translationTransform = CGAffineTransformTranslate(rotationTransform, _finalPanTranslastion.x, _finalPanTranslastion.y);self.previewImageView.transform = translationTransform;
}
复制代码

这里是最终的自定义方法,可以看到不同类型的transform是需要叠加在一起,然后最后一个transform类型赋值给视图的transform属性。

最后要主要,当有多个容易冲突的手势操作时,这些手势需要实现相应的代理方法:

// 缩放、旋转、平移手势各自签署协议
pinchGesture.delegate = self;
rotationGesture.delegate = self;
panGesture.delegate = self;// “同时生效”的代理方法
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {return YES;
}
复制代码

然后就可以操作手势来实现缩放、旋转等功能了:

三、总结

iOS开发很大一部分工作是熟悉使用系统提供的强大API,然后做适度的封装。

至于编程的另一部分——算法,数据结构,编程范式等,不分后端还是前端,都是编程者需要结合理论和实践不断提高的东西。

iOS_“图片浏览选择”功能的编写思路相关推荐

  1. html图片向两边展开效果,通过CSS3 transform实现图片浏览的几种效果

    通过css3和DOM操作,可以实现多种图片浏览的效果 但是大致思路都是一致的: 1)通过DOM操作循环创建出来一组元素 document.createElement('标签名'): 父级.append ...

  2. Linux下qt实现个人资源管理功能:记事本,图片浏览,网络聊天,数据库管理

    Linux下qt实现个人资源管理功能:记事本,图片浏览,网络聊天,数据库管理 实验内容和环境:(包括软件平台和硬件平台) QT5.14.1 Ubuntu操作系统 实验内容及步骤 (含源程序): 用QT ...

  3. android图片浏览功能,怎么在Android应用中实现一个网页图片浏览功能

    怎么在Android应用中实现一个网页图片浏览功能 发布时间:2020-12-05 17:28:31 来源:亿速云 阅读:80 作者:Leah 本篇文章给大家分享的是有关怎么在Android应用中实现 ...

  4. Android实现图片浏览功能(图片器原理实现)

    项目开发中做图片浏览的时候会用到这个功能,用原理实现的小工具 效果图: public class MainActivity extends AppCompatActivity implements V ...

  5. 制作动态相册的python知识点_动感网页相册 python编写简单文件夹内图片浏览工具...

    不知道大家有没有这样的体验,windows电脑上查看一张gif图,默认就把IE给打开了,还弹出个什么询问项,好麻烦的感觉.所以为了解决自己的这个问题,写了个简单的文件夹内图片浏览工具. 效果图 以E盘 ...

  6. Android获取相册图片-实现选择相册图片功能

    初识MediaProvider 需求:发朋友圈进行图片的选择,或者扫描二维码从图库选取...那么我们如何实现?这就需要借助媒体库的内容提供者MediaProvider,通过它,我们不仅可以读取图片,还 ...

  7. Android SmartImageView插件实现图片浏览功能

    源码下载↓↓↓ 在https://github.com网上找的小插件,实现图片浏览的简单功能,很方便. 额,简单的代码都没有几个了.. package com.example.imageview;im ...

  8. 一起撸个朋友圈吧 图片浏览(上)【图片点击前景色】

    项目地址:github.com/razerdp/Fri- (能弱弱的求个star或者fork么QAQ) 上篇链接:一起撸个朋友圈吧 (Step6)- 评论对齐(点击评论对齐)[下] 下篇链接:一起撸个 ...

  9. GraphicConverter Mac图片浏览和编辑器

    想要在您的Mac电脑上尽兴的的浏览和运用图片?或许您需要一款GraphicConverter 11 Mac版这样的图片浏览和编辑工具.GraphicConverter mac版可以打开和储存所有的图形 ...

最新文章

  1. echart折线图小知识
  2. 全球及中国手机便携式移动电源行业营销模式及投资竞争力分析报告2021-2027年版
  3. 【转】MATLAB如何制作动画(动态图形演示movie)
  4. 蓝桥练习-算法训练 P0505
  5. python代码该怎么简化_Python开发简化代码的六大技巧
  6. 查看linux的计划任务日志,查看计划任务日志(共5篇).docx
  7. MATLAB(二)数据的输入
  8. 智能巡检云监控指标的实践
  9. Android8内测申请,小米 6 安卓 8.0 来了 内测开始招募
  10. Docker详解(十)——Docker容器CPU资源限额配置
  11. 【java】判断某段字符串的编码方式,并按照新的编码方式输出
  12. 写出规范化的高可读性的函数代码注释
  13. c语言成绩管理系统(链表)
  14. 【OpenCL开发入门】01 - 搭建Visual Studio 2022+OpenCL开发环境
  15. mysql表删除后恢复
  16. 每日170219-20
  17. 计算机会考作业,计算机会考Excel操作题作业文档.doc
  18. 体系结构第1章—基本概念
  19. JetBrains PyCharm JetBrains PyCharm 2018.1.3 x64永久破解
  20. win7 改装linux系统教程,linux系统改装win7

热门文章

  1. 洛谷 P1690 贪婪的Copy
  2. 用cookie实现保存密码
  3. Redis 启动与授权
  4. VS2017 配置 OpenGL 环境
  5. 汇编--条件跳转指令
  6. deno学习一 安装试用几个问题解决
  7. Laravel Scheduling Package
  8. 字符驱动之按键(一:无脑轮询法)
  9. 利用JSON-schema校验请求报文,封装转换错误信息,提示前台
  10. shell脚本监控系统负载、CPU和内存使用情况