欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

iOS- XKZoomingView 简单的图片预览,支持横屏【手势:单击、双击、放大缩小】

程序员文章站 2022-07-28 20:54:17
XKZoomingView.h XKZoomingView.m USE ELSE ......

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 = 3;
    self.minimumzoomscale = 1;
    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 = 1;
    tapsingle.delaystouchesended = no;
    [self.mainimageview addgesturerecognizer:tapsingle];
    ///双击
    uitapgesturerecognizer *tapdouble = [[uitapgesturerecognizer alloc]initwithtarget:self action:@selector(tapdoublesponse:)];
    //设置手势属性
    tapdouble.numberoftapsrequired = 2;
    [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(0, 0)];
    [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 = 0;
        }
        else{
            imagerect.size.width = _mainimage.size.width;
            imagerect.size.height = _mainimage.size.height;
            imagerect.origin.x = (scwidth - imagerect.size.width)/2;
        }
        ///height
        if (imagerect.size.height > scheight) {
            
            imagerect.origin.y = 0;
        }
        else{
            imagerect.origin.y = (scheight - imagerect.size.height)/2;
        }
        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)/2) {
        off_x = 0;
    }
    else if (lo_x > self.contentsize.width - cgrectgetwidth(self.frame)/2){
        off_x = self.contentsize.width - cgrectgetwidth(self.frame);
    }
    else{
        off_x = lo_x - cgrectgetwidth(self.frame)/2;
    }
    
    ///off_y
    if (lo_y < cgrectgetheight(self.frame)/2) {
        off_y = 0;
    }
    else if (lo_y > self.contentsize.height - cgrectgetheight(self.frame)/2){
        if (self.contentsize.height <= cgrectgetheight(self.frame)) {
            off_y = 0;
        }
        else{
            off_y = self.contentsize.height - cgrectgetheight(self.frame);
        }
        
    }
    else{
        off_y = lo_y - cgrectgetheight(self.frame)/2;
    }
    [self setcontentoffset:cgpointmake(off_x, off_y)];
}

#pragma mark - 重置图片
- (void)resetimageviewstate{
    self.zoomscale = 1;
    _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 != 1) {
        [uiview animatewithduration:0.2 animations:^{
            self.zoomscale = 1;
        } 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 == 1) {
        [uiview animatewithduration:0.2 animations:^{
            self.zoomscale = 2.0;
            [self zoomingoffset:point];
        }];
    }
    else{
        [uiview animatewithduration:0.2 animations:^{
            self.zoomscale = 1;
        } 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 = 0;
    } else {
        imageviewframe.origin.y = (sheight - height) / 2.0;
    }
    if (width > swidth) {
        imageviewframe.origin.x = 0;
    } 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 != 1) {
        return;
    }
    _currpont = scrollview.contentoffset;
    
}
#pragma mark - 监听屏幕旋转通知
- (void)statusbarorientationchange:(nsnotification *)notification{
    self.zoomscale = 1;
}
- (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 简单的图片预览,支持横屏【手势:单击、双击、放大缩小】