XKZoomingView.h

#import <UIKit/UIKit.h>

@interface XKZoomingView : UIScrollView
/**
本地图片
*/
@property (nonatomic, strong) UIImage *mainImage; /**
图片显示
*/
@property (nonatomic, strong) UIImageView *mainImageView;
@end

XKZoomingView.m

#import "XKZoomingView.h"
@interface XKZoomingView()<UIScrollViewDelegate>
/**
当前图片偏移量
*/
@property (nonatomic,assign) CGPoint currPont;
@end
@implementation XKZoomingView - (instancetype)init{
self = [super init];
if (self) {
[self setup];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self setup];
}
return self;
}
- (void)setup{
self.backgroundColor = [[UIColor grayColor]colorWithAlphaComponent:0.2];
self.delegate = self;
self.showsHorizontalScrollIndicator = NO;
self.showsVerticalScrollIndicator = NO;
self.decelerationRate = UIScrollViewDecelerationRateFast;
self.maximumZoomScale = ;
self.minimumZoomScale = ;
self.alwaysBounceHorizontal = NO;
self.alwaysBounceVertical = NO;
self.layer.masksToBounds = YES;
if (@available(iOS 11.0, *)) {
self.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
[self addSubview:self.mainImageView]; _currPont = CGPointZero; ///监听屏幕旋转
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
///单击
UITapGestureRecognizer *tapSingle = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapSingleSponse:)];
//设置手势属性
tapSingle.numberOfTapsRequired = ;
tapSingle.delaysTouchesEnded = NO;
[self.mainImageView addGestureRecognizer:tapSingle];
///双击
UITapGestureRecognizer *tapDouble = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapDoubleSponse:)];
//设置手势属性
tapDouble.numberOfTapsRequired = ;
[self.mainImageView addGestureRecognizer:tapDouble];
///避免手势冲突
[tapSingle requireGestureRecognizerToFail:tapDouble];
} #pragma mark - layoutSubviews
- (void)layoutSubviews{
[super layoutSubviews];
///放大或缩小中
if (self.zooming || self.zoomScale != 1.0 || self.zoomBouncing) {
return;
} ///设置图片尺寸
if (_mainImage) {
CGRect imgRect = [self getImageViewFrame];
self.mainImageView.frame = imgRect;
///设置content size
if (CGRectGetHeight(imgRect) > CGRectGetHeight(self.frame)) {
[self setContentSize:CGSizeMake(CGRectGetWidth(self.frame), CGRectGetHeight(imgRect))];
}
else{
[self setContentSize:CGSizeMake(CGRectGetWidth(self.frame), CGRectGetHeight(self.frame))];
}
} }
- (void)setMainImage:(UIImage *)mainImage{
_mainImage = mainImage;
self.mainImageView.image = _mainImage;
[self setContentOffset:CGPointMake(, )];
[self setNeedsLayout];
} /**
根据图片原始大小,获取图片显示大小
@return CGRect
*/
- (CGRect)getImageViewFrame{
if (_mainImage) {
CGRect imageRect;
CGFloat scWidth = self.frame.size.width;
CGFloat scHeight = self.frame.size.height;
///width
if (_mainImage.size.width > scWidth) {
imageRect.size.width = scWidth;
CGFloat ratioHW = _mainImage.size.height/_mainImage.size.width;
imageRect.size.height = ratioHW * imageRect.size.width;
imageRect.origin.x = ;
}
else{
imageRect.size.width = _mainImage.size.width;
imageRect.size.height = _mainImage.size.height;
imageRect.origin.x = (scWidth - imageRect.size.width)/;
}
///height
if (imageRect.size.height > scHeight) { imageRect.origin.y = ;
}
else{
imageRect.origin.y = (scHeight - imageRect.size.height)/;
}
return imageRect;
}
return CGRectZero;
}
/**
获取点击位置后所需的偏移量【目的是呈现点击位置在试图上】 @param location 点击位置
*/
- (void)zoomingOffset:(CGPoint)location{
CGFloat lo_x = location.x * self.zoomScale;
CGFloat lo_y = location.y * self.zoomScale; CGFloat off_x;
CGFloat off_y;
///off_x
if (lo_x < CGRectGetWidth(self.frame)/) {
off_x = ;
}
else if (lo_x > self.contentSize.width - CGRectGetWidth(self.frame)/){
off_x = self.contentSize.width - CGRectGetWidth(self.frame);
}
else{
off_x = lo_x - CGRectGetWidth(self.frame)/;
} ///off_y
if (lo_y < CGRectGetHeight(self.frame)/) {
off_y = ;
}
else if (lo_y > self.contentSize.height - CGRectGetHeight(self.frame)/){
if (self.contentSize.height <= CGRectGetHeight(self.frame)) {
off_y = ;
}
else{
off_y = self.contentSize.height - CGRectGetHeight(self.frame);
} }
else{
off_y = lo_y - CGRectGetHeight(self.frame)/;
}
[self setContentOffset:CGPointMake(off_x, off_y)];
} #pragma mark - 重置图片
- (void)resetImageViewState{
self.zoomScale = ;
_mainImage = nil;;
self.mainImageView.image = nil; }
#pragma mark - 变量
- (UIImageView *)mainImageView {
if (!_mainImageView) {
_mainImageView = [UIImageView new];
_mainImageView.image = nil;
_mainImageView.contentMode = UIViewContentModeScaleAspectFit;
_mainImageView.userInteractionEnabled = YES;
}
return _mainImageView;
} #pragma mark - 单击
- (void)tapSingleSponse:(UITapGestureRecognizer *)singleTap{
if (!self.mainImageView.image) {
return;
} if (self.zoomScale != ) {
[UIView animateWithDuration:0.2 animations:^{
self.zoomScale = ;
} completion:^(BOOL finished) {
[self setContentOffset:_currPont animated:YES];
}];
}
}
#pragma mark - 双击
- (void)tapDoubleSponse:(UITapGestureRecognizer *)doubleTap{
if (!self.mainImageView.image) {
return;
}
CGPoint point = [doubleTap locationInView:self.mainImageView];
if (self.zoomScale == ) {
[UIView animateWithDuration:0.2 animations:^{
self.zoomScale = 2.0;
[self zoomingOffset:point];
}];
}
else{
[UIView animateWithDuration:0.2 animations:^{
self.zoomScale = ;
} completion:^(BOOL finished) {
[self setContentOffset:_currPont animated:YES];
}];
}
} #pragma mark - UIScrollViewDelegate
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
if (!self.mainImageView.image) {
return;
}
CGRect imageViewFrame = self.mainImageView.frame;
CGFloat width = imageViewFrame.size.width,
height = imageViewFrame.size.height,
sHeight = scrollView.bounds.size.height,
sWidth = scrollView.bounds.size.width;
if (height > sHeight) {
imageViewFrame.origin.y = ;
} else {
imageViewFrame.origin.y = (sHeight - height) / 2.0;
}
if (width > sWidth) {
imageViewFrame.origin.x = ;
} else {
imageViewFrame.origin.x = (sWidth - width) / 2.0;
}
self.mainImageView.frame = imageViewFrame;
} - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.mainImageView;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
if (self.isZooming || self.zoomScale != ) {
return;
}
_currPont = scrollView.contentOffset; }
#pragma mark - 监听屏幕旋转通知
- (void)statusBarOrientationChange:(NSNotification *)notification{
self.zoomScale = ;
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];
} @end

USE

XKZoomingView *zoomView = [[XKZoomingView alloc]init];
zoomView.frame = self.view.bounds;
zoomView.mainImage = [UIImage imageNamed:@""];
[self.view addSubview:zoomView];

ELSE

iOS- XKZoomingView 简单的图片缩放预览,支持横屏、长图【手势:单击、双击、放大缩小】的更多相关文章

  1. Android仿微信图片上传,可以选择多张图片,缩放预览,拍照上传等

    仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...

  2. iOS HTML图片本地预览

    引言 相信用过苹果手机的童鞋,会发现很多新闻类的应用,都可以实现HTML图片本地预览,那么这是如何实现的呢?本文将深入阐述其中的原理. 关于此功能,我还实现了一个DEMO,大家可以点击此访问更详细内容 ...

  3. Android图片上传,可以选择多张图片,缩放预览,拍照上传等

    仿照微信,朋友圈分享图片功能 .可以进行图片的多张选择,拍照添加图片,以及进行图片的预览,预览时可以进行缩放,并且可以删除选中状态的图片 .很不错的源码,大家有需要可以下载看看 . 微信 微信 微信 ...

  4. Azure SQL 数据库的灵活缩放预览版简介

    Eron Kelly SQL Server 产品管理部门产品市场营销总经理 几天前,我们宣布了发布 Azure SQL 数据库的灵活缩放公共预览版.新增的灵活缩放功能通过简化开发和管理,简化了扩展和缩 ...

  5. Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换

    如何调用本地图片,并调用系统拍摄的图像上一博文解释(http://blog.csdn.net/a123demi/article/details/40003695)的功能. 而本博文将通过实例实现自己定 ...

  6. js实现FileUpload选择图片后预览功能

    当asp.net的FileUpload选择一个图片后不需要上传就能显示出图片的预览功能, 代码: <%@ Page Language="C#" AutoEventWireup ...

  7. 图片本地预览 flash html5

    dataURI 一种能够在页面嵌入外部资源的URI方案.能够降低图片或者样式表的http请求数量,提高效率. ie8把dataURI 的属性值限制在32k以内. 图片本地预览: 由于安全原因,通过fi ...

  8. 巧用weui.gallery(),点击图片后预览图片

    要在页面需要加载的JS文件: <script src="../js/libs/weui.min.js"></script> 可以去weui的文档中下载,这是 ...

  9. node.js平台下,cropper.js实现图片裁剪预览并转换为base64发送至服务端。

    一 .准备工作 1.首先需要先下载cropper,常规使用npm,进入项目路径后执行以下命令: npm install cropper 2. cropper基于jquery,在此不要忘记引入jq,同时 ...

随机推荐

  1. Tomcat常用设置及安全管理规范

    前言 随着公司内部使用Tomcat作为web应用服务器的规模越来越大,为保证Tomcat的配置安全,防止信息泄露,恶性攻击以及配置的安全规范,特制定此Tomcat安全配置规范.注意:  本文章从htt ...

  2. 获取MessageBox按钮本地字符串(OK、Cancel、Yes、No等)

    问题仍然由定制MessageBox引发. 定制MessageBox,虽加入自定义些东西,但仍然希望,最大限度接近系统原生框.碰到的问题,就是其钮文本. 即如MessageBox.Show()之Mess ...

  3. 配置apache虚拟域名(phpStudy2016)

    以前也一个个的配置过apache.php和mysql,现在嫌麻烦,就用的phpStudy. 装好之后,发现127.0.0.1可以访问,但是localhost就不可以访问.大概是因为apache没有配置 ...

  4. Mad Libs游戏1

    简单的输入输出 输入代码 name1=input('请输入姓名:') name2=input('请输入一个句子:') name3=input('请输入一个地点:') name4=input('请输入一 ...

  5. Spring Boot-右键maven build成功但是直接运行main方法出错的解决方案

    1.代码就一个Controller,从官网复制过来的,如下 package com.springboot.controller; import org.springframework.boot.Spr ...

  6. Spring 配置文件中 元素 属性 说明

    <beans /> 元素 该元素是根元素.<bean /> 元素的属性 default-init // 是否开启懒加载.默认为 false default-dependency ...

  7. boost asio 学习(四)使用strand将任务排序

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=5 4. Seri ...

  8. python_day12_css

    目录: 简介 选择器(selecttor) 常用属性 页面布局 一.简介 1.CSS 定义 CSS是Cascading Style Sheets的简称,中文称为层叠样式表. CSS 规则由两个主要的部 ...

  9. C#中 property 与 attribute的区别

    说的通俗些Attribute是类,不过是一类比较特殊的类,Attribute必须写在一对方括号中,用来处理.NET中多种问题:序列化.程序的安全特征等等,在.NET中的作用非同凡响 Attribute ...

  10. nginx简单权限配置

    一.指定ip段 location / { allow 172.17.0.1/24; deny all; } 二.指定认证账户 location / { auth_basic "please ...