美文网首页IOS知识积累
iOS-图片的预览功能(放大,缩小,等手势)的轮子

iOS-图片的预览功能(放大,缩小,等手势)的轮子

作者: iOS_Edward | 来源:发表于2017-04-24 14:09 被阅读0次

    关于图片的预览在很多的地方都可以用到,去年做的一个商城类的项目中就仿照淘宝预览图片效果写了一个对于UIWebview上图片的预览功能的工具类,其实就是一个view,使用起来也很方便,前两天做项目时也又有用到,在此分享给有需要的人,以下是代码:

    #import <UIKit/UIKit.h>
    @protocol PhotoShowViewDelegate;
    @interface PhotoShowView : UIView
    @property(nonatomic,weak,nullable)id<PhotoShowViewDelegate> delegate;
    
    @property(nonatomic,assign)BOOL enableTapTwo;       //是否允许双击,默认YES
    @property(nonatomic,assign)BOOL enableRotation;     //是否允许旋转,默认YES
    @property(nonatomic,assign)BOOL enablePinch;        //是否允许绽放,默认YES
    @property(nonatomic,assign)BOOL enablePan;          //是否允许平移,默认YES
    @property(nonatomic,assign)BOOL enableReset;        //是否自动复位,默认YES
    @property(nonatomic,assign)NSInteger panFingerNum;  //平移时用的手指数,默认为2
    @property(nonatomic,assign)CGFloat minScale;      //最小绽放比例,默认0.3
    @property(nonatomic,assign)CGFloat maxScale;      //最大绽放比例,默认5.0
    @property(nonatomic,assign)CGFloat doubleTapScale;//双击时的绽放比例,默认为2;
    @property(nonatomic,strong,nullable)UIImageView* imageView; //要显示的图片
    -(nonnull instancetype)initWithFrame:(CGRect)frame NS_DEPRECATED_IOS(2_0, 3_0);
    -(nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder NS_DEPRECATED_IOS(2_0, 3_0);
    -(void)resetTransform;
    @end
    @protocol PhotoShowViewDelegate <NSObject>
    @optional
    -(void)photoShowViewTouchBegan:(nullable PhotoShowView*)psv;
    -(void)photoShowViewTouchEnd:(nullable PhotoShowView*)psv;
    -(void)photoShowViewPhotoReduction:(nullable PhotoShowView*)psv;//相片被还原时的回调
    @end
    
    #import "PhotoShowView.h"
    @interface PhotoShowView ()<UIGestureRecognizerDelegate>{
        UITapGestureRecognizer *_gesTapTwo;
        UIRotationGestureRecognizer *_gesRotation;
        UIPinchGestureRecognizer *_gesPinch;
        UIPanGestureRecognizer *_gesPan;
        
        BOOL _hadGesEndPan;
        BOOL _hadGesEndPinch;
        BOOL _hadGesEndRotation;
        
        BOOL _animating;
        
        CGFloat _scale;
        CGFloat _theScale;
        CGFloat _rotation;
        CGFloat _theRotation;
        CGFloat _pointX;
        CGFloat _thePointX;
        CGFloat _pointY;
        CGFloat _thePointY;
        
        BOOL _touchBegin;
        BOOL _hadAfterReset;
    }
    @end
    @implementation PhotoShowView
    -(instancetype)init{
        self=[super init];
        if (self){
            [self initializeVariable];
            [self createUI];
            [self addUI];
        }
        return self;
    }
    -(instancetype)initWithFrame:(CGRect)frame{
        return [super initWithFrame:frame];
    }
    -(instancetype)initWithCoder:(NSCoder *)aDecoder{
        return [super initWithCoder:aDecoder];
    }
    -(void)initializeVariable{
        _theTag=0;
        _theTagString=@"";
        _theTagUserInfo=[NSMutableDictionary dictionaryWithCapacity:0];
        
        _enableTapTwo=YES;
        _enableRotation=YES;
        _enablePinch=YES;
        _enablePan=YES;
        _enableReset=YES;
        _panFingerNum=2;
        _minScale=0.2;
        _maxScale=5.0;
        _doubleTapScale=2.0;
        
        [self initializeTouch];
        
        _animating=NO;
        
        _hadGesEndPan=YES;
        _hadGesEndPinch=YES;
        _hadGesEndRotation=YES;
        
        _touchBegin=NO;
        _hadAfterReset=NO;
    }
    -(void)initializeTouch{
        _scale=1.0;
        _theScale=1.0;
        _rotation=0.0;
        _theRotation=0.0;
        _pointX=0;
        _thePointX=0;
        _pointY=0;
        _thePointY=0;
    }
    -(void)createUI{
        _imageView=[[UIImageView alloc] init];
        _imageView.userInteractionEnabled=NO;
        _imageView.backgroundColor=[UIColor clearColor];
        _imageView.contentMode=UIViewContentModeScaleAspectFit;
        
        _gesTapTwo=[[UITapGestureRecognizer alloc] init];
        [_gesTapTwo addTarget:self action:@selector(gesBeTouchInPhotoShowView:)];
        _gesTapTwo.numberOfTapsRequired=2;
        _gesTapTwo.delegate=self;
        
        _gesRotation=[[UIRotationGestureRecognizer alloc] init];
        [_gesRotation addTarget:self action:@selector(gesBeTouchInPhotoShowView:)];
        _gesRotation.delegate=self;
        
        _gesPinch=[[UIPinchGestureRecognizer alloc] init];
        [_gesPinch addTarget:self action:@selector(gesBeTouchInPhotoShowView:)];
        _gesPinch.delegate=self;
        
        _gesPan=[[UIPanGestureRecognizer alloc] init];
        [_gesPan addTarget:self action:@selector(gesBeTouchInPhotoShowView:)];
        _gesPan.delegate=self;
        _gesPan.minimumNumberOfTouches=_panFingerNum;
    }
    -(void)addUI{
        [self addSubview:_imageView];
        
        [self addGestureRecognizer:_gesTapTwo];
        [self addGestureRecognizer:_gesRotation];
        [self addGestureRecognizer:_gesPinch];
        [self addGestureRecognizer:_gesPan];
    }
    -(void)layoutSubviews{
        [super layoutSubviews];
        [self layoutAuto];
    }
    -(void)layoutAuto{
        if (!_animating) {
            _imageView.frame=self.bounds;
        }
    }
    #pragma mark - 手势
    -(void)gesBeTouchInPhotoShowView:(UIGestureRecognizer*)ges{
        if (ges==_gesTapTwo) {
            if (_enableTapTwo) {
                if (_gesTapTwo.state==UIGestureRecognizerStateEnded) {
                    if (_theScale==1.0) {
                        _theScale=_doubleTapScale;
                        _scale=1.0;
                    }else{
                        _theScale=1.0;
                        _scale=1.0;
                    }
                    [self imageTransformWithAnimate:YES];
                }
            }
        }
        if(ges==_gesRotation){
            if (_enableRotation) {
                _hadGesEndRotation=NO;
                _rotation=_gesRotation.rotation;
                [self imageTransformWithAnimate:NO];
                if (_gesRotation.state==UIGestureRecognizerStateEnded) {
                    _theRotation+=_rotation;
                    _rotation=0.0;
                    _hadGesEndRotation=YES;
                    [self afterReduction];
                }
            }
        }
        if(ges==_gesPinch){
            if (_enablePinch) {
                _hadGesEndPinch=NO;
                _scale=_gesPinch.scale;
                [self imageTransformWithAnimate:NO];
                if (_gesPinch.state==UIGestureRecognizerStateEnded) {
                    _theScale*=_scale;
                    _scale=1.0;
                    _hadGesEndPinch=YES;
                    [self afterReduction];
                }
            }
        }
        if(ges==_gesPan){
            if (_enablePan) {
                _hadGesEndPan=NO;
                CGPoint point=[_gesPan translationInView:self];
                _pointX=point.x;
                _pointY=point.y;
                [self imageTransformWithAnimate:NO];
                if (_gesPan.state==UIGestureRecognizerStateEnded) {
                    _thePointX+=_pointX;
                    _thePointY+=_pointY;
                    _pointX=0.0;
                    _pointY=0.0;
                    _hadGesEndPan=YES;
                    [self afterReduction];
                }
            }
        }
        if (_gesPan.state==UIGestureRecognizerStateChanged||
            _gesPinch.state==UIGestureRecognizerStateChanged||
            _gesRotation.state==UIGestureRecognizerStateChanged) {
            
            if (!_touchBegin) {
                _touchBegin=YES;
                [self delegatePhotoShowViewTouchBegan:self];
            }
            
        }else{
            if (_touchBegin) {
                _touchBegin=NO;
                [self delegatePhotoShowViewTouchEnd:self];
            }
        }
    }
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    #pragma mark - 图片形变
    -(void)imageTransformWithAnimate:(BOOL)ani{
        _animating=YES;
        CGFloat newScale=_scale*_theScale;
        if (newScale>=_maxScale) {
            newScale=_maxScale;
            _scale=1.0;
            _theScale=_maxScale;
        }
        if (newScale<=_minScale) {
            newScale=_minScale;
            _scale=1.0;
            _theScale=_minScale;
        }
        CGAffineTransform t=CGAffineTransformMakeScale(newScale, newScale);
        t=CGAffineTransformRotate(t, _rotation+_theRotation);
        t=CGAffineTransformTranslate(t, _pointX+_thePointX, _pointY+_thePointY);
        if (ani) {
            [UIView animateWithDuration:0.26 animations:^{
                _imageView.transform=t;
            }];
        }else{
            _imageView.transform=t;
        }
    //    NSLog(@"_scale==%.2f",_scale);
    //    NSLog(@"_theScale==%.2f",_theScale);
    //    NSLog(@"_rotation==%.2f",_rotation);
    //    NSLog(@"_theRotation==%.2f",_theRotation);
    //    NSLog(@"%@",NSStringFromCGAffineTransform(t));
    //    NSLog(@"_imageView.frame==%@",NSStringFromCGRect(_imageView.frame));
    }
    -(void)afterReduction{
        if (_enableReset) {
            _hadAfterReset=NO;
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)1000*NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
                if (_hadGesEndPan&&_hadGesEndPinch&&_hadGesEndRotation) {
                    if (!_hadAfterReset) {
                        _hadAfterReset=YES;
                        [self transformToZero];
                    }
                    
                }
            });
        }
    }
    -(void)resetTransform{
        [self transformToZero];
    }
    -(void)transformToZero{
        [self initializeTouch];
        [self imageTransformWithAnimate:YES];
        _animating=NO;
        [self setNeedsLayout];
        [self delegatePhotoShowViewPhotoReduction:self];
    }
    #pragma mark - set get
    -(void)setPanFingerNum:(NSInteger)panFingerNum{
        _panFingerNum=panFingerNum;
        _gesPan.minimumNumberOfTouches=_panFingerNum;
    }
    #pragma mark - delegate
    -(void)delegatePhotoShowViewTouchBegan:(nullable PhotoShowView*)psv{
        if ([_delegate respondsToSelector:@selector(photoShowViewTouchBegan:)]) {
            [_delegate photoShowViewTouchBegan:psv];
        }
    }
    -(void)delegatePhotoShowViewTouchEnd:(nullable PhotoShowView*)psv{
        if ([_delegate respondsToSelector:@selector(photoShowViewTouchEnd:)]) {
            [_delegate photoShowViewTouchEnd:psv];
        }
    }
    -(void)delegatePhotoShowViewPhotoReduction:(nullable PhotoShowView*)psv{
        if ([_delegate respondsToSelector:@selector(photoShowViewPhotoReduction:)]) {
            [_delegate photoShowViewPhotoReduction:psv];
        }
    }
    @end
    

    使用起来也很方便,就直接当做一个view来使用,内部已经实现了对图片的各种手势操作,因为当时本来就是当做自己使用的轮子,所以代码中的注释不多,大家都是成人了,就直接自己看就好了吧.

    希望以上代码对大家有所帮助.

    相关文章

      网友评论

        本文标题:iOS-图片的预览功能(放大,缩小,等手势)的轮子

        本文链接:https://www.haomeiwen.com/subject/vwcpzttx.html