来源:伯乐在线 - 小良

如有好文章投稿,请点击 → 这里了解详情

如需转载,发送「转载」二字查看说明

公司产品需要实现点击个人主页头像可以放大头像、缩放头像、保存头像效果(和点击微信个人头像类似),故找个时间实现一下,记录下来,供自己查看,也给大家做个参考。

实现效果(GIF):

实现思路:

直接自定义 UIView(CYPhotoPreviewer),为了实现双击缩放,可以实现 UIScrollViewDelegate 对应的方法。如果需要模糊背景,可以在自定义的 UIView 中先添加模糊背景,再添加 UIScrollView,继而在 UIScrollView 中添加图片容器,这个容器就是要显示的图片的 superView,代码一目了然:

- (void)setup {

self.frame = [UIScreen mainScreen].bounds;

self.backgroundColor = [UIColor clearColor];

UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];

[self addGestureRecognizer:singleTap];

UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(doubleTap:)];

doubleTap.numberOfTapsRequired = 2;

[singleTap requireGestureRecognizerToFail:doubleTap];

[self addGestureRecognizer:doubleTap];

UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:selfaction:@selector(longPress:)];

[self addGestureRecognizer:longPress];

// 设置模糊背景

self.blurBackground = [[UIVisualEffectView alloc] initWithEffect:[UIBlurEffecteffectWithStyle:UIBlurEffectStyleExtraLight]];

self.blurBackground.frame = self.frame;

[self addSubview:self.blurBackground];

// 设置 UIScrollView 相关属性

self.scrollView = [[UIScrollView alloc] initWithFrame:[UIScreen mainScreen].bounds];

self.scrollView.delegate = self;

self.scrollView.bouncesZoom = YES;

self.scrollView.maximumZoomScale = 3.0;

self.scrollView.multipleTouchEnabled = YES;

self.scrollView.alwaysBounceVertical = NO;

self.scrollView.showsVerticalScrollIndicator = NO;

self.scrollView.showsHorizontalScrollIndicator = NO;

[self addSubview:self.scrollView];

// containerView

self.containerView = [[UIView alloc] init];

[self.scrollView addSubview:self.containerView];

// imageView

self.imageView = [[UIImageView alloc] init];

self.imageView.clipsToBounds = YES;

self.imageView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.5];

[self.containerView addSubview:self.imageView];

}

可以看到,我们给设置了模糊背景,给这个 CYPhotoPreviewer 添加了单击手势(关闭 PhotoPreviewer)、双击手势(缩放图片)、长按手势(使用 UIAlertController 菜单,比如保存图片等)。

好,确定了这个 CYPhotoPreviewer 中的显示内容,那么我们该如何显示这个 CYPhotoPreviewer 呢?

  • 直接将这个 CYPhotoPreviewer 添加到 keyWindow 上

  • 将这个 CYPhotoPreviewer 添加到控制器的 self.view 上

这两种方式的实现都差不多,不过如果使用第一种方式的话,会导致将 CYPhotoPreviewer 添加到 keyWindow 上之后,再长按继续将 UIAlertController 显示就比较麻烦了,因此,这里打算采用将 CYPhotoPreviewer 添加到控制器的 self.view 上,继而就可以很方便的显示 UIAlertController 了:

- (void)previewFromImageView:(UIImageView *)fromImageView inContainer:(UIView *)container {

_fromImageView = fromImageView;

fromImageView.hidden = YES;

[container addSubview:self]; // 将 CYPhotoPreviewer 添加到 container 上

self.containerView.origin = CGPointZero;

self.containerView.width = self.width; // containerView 的宽度是屏幕的宽度

UIImage *image = fromImageView.image;

// 计算 containerView 的高度

if (image.size.height / image.size.height > self.height / self.width) {

self.containerView.height = floor(image.size.height / (image.size.width / self.width));

} else {

CGFloat height = image.size.height / image.size.width * self.width;

if (height  self.height && self.containerView.height - self.height

可以看到,我们将外面的图片 fromImageView 传递进来,是为了显示更好的动画效果;将控制器的 container(self.view)传递进来,是为了将 CYPhotoPreviewer 添加到 container 的细节不需要在调用处处理,即初始化 CYPhotoPreviewer 之后,CYPhotoPreviewer 就直接被 container 添加为 subview 了。动画很简单不再细说。

显示的效果已经做好,单击关闭 CYPhotoPreviewer 也比较好实现,只需要从父类移除 CYPhotoPreviewer 即可:

- (void)dismiss {

[UIView animateWithDuration:0.18 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{

CGRect fromRect = [self.fromImageView convertRect:self.fromImageView.bounds toView:self.containerView];

self.imageView.contentMode = self.fromImageView.contentMode;

self.imageView.frame = fromRect;

self.blurBackground.alpha = 0.01;

} completion:^(BOOL finished) {

[UIView animateWithDuration:0.10 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{

self.fromImageView.hidden = NO;

self.alpha = 0;

} completion:^(BOOL finished) {

[self removeFromSuperview];

}];

}];

}

好了,显示和关闭 CYPhotoPreviewer 都实现了,如果需要双击缩放图片效果,就得实现 UIScrollViewDelegate 的两个方法以及 CYPhotoPreviewer 的双击手势:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{

return self.containerView;

}

- (void)scrollViewDidZoom:(UIScrollView *)scrollView {

UIView *subView = self.containerView;

CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)?

(scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;

CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)?

(scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;

subView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX,

scrollView.contentSize.height * 0.5 + offsetY);

}

- (void)doubleTap:(UITapGestureRecognizer *)recognizer {

if (self.scrollView.zoomScale > 1.0) {

[self.scrollView setZoomScale:1.0 animated:YES];

} else {

CGPoint touchPoint = [recognizer locationInView:self.imageView];

CGFloat newZoomScale = self.scrollView.maximumZoomScale;

CGFloat xSize = self.width / newZoomScale;

CGFloat ySize = self.height / newZoomScale;

[self.scrollView zoomToRect:CGRectMake(touchPoint.x - xSize / 2, touchPoint.y - ySize / 2, xSize, ySize)animated:YES];

}

}

最后一个就是长按弹出菜单(UIAlertController)了:

- (void)longPress:(UILongPressGestureRecognizer *)recognizer {

// 为了避免弹警告:Warning: Attempt to present   on  which is already presenting ,最好加入状态判断

if (recognizer.state == UIGestureRecognizerStateBegan) {

UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"QuoraDots" message:nilpreferredStyle:UIAlertControllerStyleActionSheet];

[alertController addAction:[UIAlertAction actionWithTitle:@"保存" style:UIAlertActionStyleDefault handler:nil]];

[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];

UIViewController *vc = self.viewController;

[vc presentViewController:alertController animated:YES completion:nil];

}

}

注意一点,longPress: 这个方法会调用很频繁,因此,为了避免 Attempt to present xxx on xxx which is already presenting xxx 这个警告,我们需要判断手势的状态。

后话:

这个只是显示单张图片的大图,如果需要显示多张图片类似微信微博的九宫格图片的大图显示,则需要将这个 CYPhotoPreviewer 搞成 UICollectionView 的 item 即可,大家可以尝试尝试。最后,如果需要或者 CYPhotoPreviewer 源码,可以前往

iOS 实现点击微信头像效果相关推荐

  1. 实现点击微信头像实现放大头像、缩放头像、保存头像效果

    实现点击个人主页头像可以放大头像.缩放头像.保存头像效果(和点击微信个人头像类似). 实现思路: 直接自定义 UIView(CYPhotoPreviewer),为了实现双击缩放,可以实现 UIScro ...

  2. php 微信头像 圆形,详解iOS 裁剪圆形图像并显示(类似于微信头像)

    本文主要讲解如何从照片库选择一张照片后将其裁剪成圆形头像并显示,类似于微信头像那种模式. 本文的方法也适用于当时拍照获取的图像,方法类似,所以不再赘述. 本文主要是在ios 10环境下使用,此时如果要 ...

  3. ios 裁剪圆形头像_iOS 裁剪圆形图像并显示(类似于微信头像)

    本文主要讲解如何从照片库选择一张照片后将其裁剪成圆形头像并显示,类似于微信头像那种模式. 本文的方法也适用于当时拍照获取的图像,方法类似,所以不再赘述. 本文主要是在iOS 10环境下使用,此时如果要 ...

  4. ios 裁剪圆形头像_详解iOS 裁剪圆形图像并显示(类似于微信头像)

    本文主要讲解如何从照片库选择一张照片后将其裁剪成圆形头像并显示,类似于微信头像那种模式. 本文的方法也适用于当时拍照获取的图像,方法类似,所以不再赘述. 本文主要是在iOS 10环境下使用,此时如果要 ...

  5. ios 点击出现另外一套tabbar_iOS开发中TabBar再次点击实现刷新效果

    需求 之前已经实现了自定义TabBar,如图所示: 自定义TabBar.jpeg 现在需要实现一个类似今日头条TabBar的功能 -- 如果继续点击当前TabBar的选中项,那么该界面需要刷新UITa ...

  6. Android学习之Android 5.0分享动画实现微信点击全屏效果

    Android5.0过渡动画,请看 http://blog.csdn.net/qq_16131393/article/details/51112772 今天用分享动画实现微信点击全屏效果 本文源代码下 ...

  7. Android仿微信头像放大效果

    android仿微信头像放大效果,使用Dialog+Gallery 实现 1.  dialog显示时的动画style,动画可以自己根据喜好自己设置,此处动画xml省略 <style name=& ...

  8. tree.js 酷炫的效果,人脸识别签到思路,html5 3D微信头像自动抽奖代码

    1.酷炫效果 1.1 网址: https://wow.techbrood.com/fiddle/43962 网址:https://wow.techbrood.com/fiddle/25678 1.2  ...

  9. android 点击图片动画效果,Android仿微信图片点击全屏效果

    废话不多说,先看下Android图片点击全屏效果: 先是微信的 再是模仿的 先说下实现原理,再一步步分析 这里总共有2个Activity一个就是主页,一个就是显示我们图片效果的页面,参数通过Inten ...

最新文章

  1. DDP、DDU、DAP的区别你都知道吗?
  2. GNU make manual 翻译( 一百一十四)
  3. C++11 initializer_list 和 Range-based for loop 学习理解
  4. 3D人脸识别预处理,3D face recognition preprocess
  5. SpringBoot与MyBatis技术集成
  6. 数学建模学习笔记(四)——拟合算法
  7. Windows脚本编码器算法分析与破译
  8. iOS开发基础篇——介绍C++内置函数
  9. mib 文件中的 rowstatus 参数_k8s yaml格式的pod定义文件详解
  10. java 正则 关键字_正则表达式关键字
  11. c语言选择循环实验报告,C语言程序设计实验报告选择与循环结构程序设计.doc
  12. oracle如何杀掉表死锁,oracle杀死死锁的方法
  13. android 模拟gps坐标,1020. Android GPS定位欺骗(模拟定位)的3类途径4种方式
  14. 讨论一下hibernate如何动态注册一个动态生成的实体类
  15. JS表单验证之正则表达式
  16. matlab 直方图 拟合,MATLAB 直方图拟合
  17. Clark与Park变换详解
  18. 中巴地球资源(CBERS)卫星系列介绍
  19. 萤石云视频监控接入详细流程,添加设备,展示视频,云台控制
  20. 拖拽 开发 easyui php,jQuery EasyUI 教程-Draggable(拖动)

热门文章

  1. [deviceone开发]-一个很炫的手势动画示例
  2. 5个常用Java代码混淆器 助你保护你的代码
  3. flash 入门课知识小结
  4. UITextField的详细使用
  5. CentOS Linux内核升级全过程
  6. linux内核map图
  7. HTTP长连接服务器端推技术
  8. 用C#编写获取远程IP,MAC的方法
  9. .Net2.0 使用ConfigurationManager读写配置文件
  10. 用ASP.NET上传大文件