iOS学习之图片放大,滑动浏览

iOS许多APP中都使用到了图片放大浏览的功能,如淘宝、微信等。最近也琢磨了一些方法,基本可以实现点击图片放大,并且可以左右滑动浏览上一张下一张图片,也可以通过手势撑开放大缩小,可以加上长按保存到相册的功能。具体的做法是子类化UIImageView,添加点击手势,监听手势创建UIScrollView浏览视图,实现左右滑动,每张图片用独自的UIScrollView盛放便可以实现放大缩小旋转等功能

一、效果

浏览效果和放大效果

            

二、实现流程

1、子类化UIImageView,取名为ZoomImageView

#import <UIKit/UIKit.h>

@class ZoomImageView;
@protocol ZoomImageViewDelegate <NSObject>
@optional
//图片将要放大
- (void)imageWillZoomIn:(ZoomImageView *)imageView;
//图片已经放大
- (void)imageDidZoomIn:(ZoomImageView *)imageView;
//图片将要隐藏
- (void)imageWillZoomOut:(ZoomImageView *)imageView;
//图片已经隐藏
- (void)imageDidZoomOut:(ZoomImageView *)imageView;
@end

@interface ZoomImageView : UIImageView {
    UIImageView *_fullImageView;
}
@property (nonatomic, weak)id<ZoomImageViewDelegate> delegate;
//绑定数据用于浏览
@property (nonatomic,strong)NSMutableArray *imageArray;
//描述
@property (nonatomic,strong)NSMutableArray *desArray;
//当前图片
@property (nonatomic,strong)NSString *nowImage;
- (instancetype)initWithFrame:(CGRect)frame withImage:(NSString *)imageStr;
2、给ZoomImageView添加点击事件,实现放大动画

//是否处于点击状态   
 _isTap = NO;
//添加点击手势
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(zoomAction)];
[self addGestureRecognizer:tap];
self.userInteractionEnabled = YES;
//等比例放大缩小
self.contentMode = UIViewContentModeScaleAspectFit;

实现ZoomAction图片放大方法,当zoomImageView 被点击,用[self _createViews]创建放大所需的视图。然后显示_maskView,_maskView的背景设置为黑色,这样原来的图片就将被黑色覆盖,接着获取被点击的图片的frame,将_fullImageView的的坐标设置为被点击图片的坐标,用_fullImageView实现放大动画,放大完成后_fullImageView再次隐藏并移除,这样就实现了放大功能。最后显示用于图片滑动浏览的_photoListView视图。

- (void)zoomAction{
    if (_isTap == YES) {
        return;
    }else{
        _isTap = YES;
    }
    NSLog(@"开始放大");
    //调用代理对象将要放大的协议方法
    if ([self.delegate respondsToSelector:@selector(imageWillZoomIn:)]) {
        [self.delegate imageWillZoomIn:self];
    }
    [self _createView];
    //坐标系由当前视图转化为window的坐标
    CGRect frame = [self convertRect:self.bounds toView:self.window];
  
    _fullImageView.frame = frame;
    _maskView.alpha = 1;
    _maskView.hidden = NO;
    
    //设置动画效果实现放大
    [UIView animateWithDuration:0.3 animations:^{
        //放大到整个屏幕
        _fullImageView.frame = [UIScreen mainScreen].bounds;
        
    } completion:^(BOOL finished) {
        
        _photoListView.hidden = NO;
        _maskView.hidden = NO;
        _fullImageView.hidden = YES;
        
        //调用代理对象已经放大的协议方法
        if ([self.delegate respondsToSelector:@selector(imageDidZoomIn:)]) {
            [self.delegate imageDidZoomIn:self];
        }
    }];
}
当图片被点击的时候,创建放大所需的视图,_maskView为黑色背景视图,_photoListView继承UIView,用于放置浏览图片的视图,_fullImageView继承自UIImageView,用于实现图片放大动画
//创建大图显示时需要的子视图
- (void)_createView {
    
    if (_photoListView == nil) {
       
        //蒙砂视图
        _maskView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
        _maskView.backgroundColor = [UIColor blackColor];
        _maskView.alpha = 1;
        _maskView.hidden = YES;
        [self.window addSubview:_maskView];
        
        //图片浏览视图
        _photoListView = [[PhotoListView alloc] initWithFrame:[UIScreen mainScreen].bounds];
        _photoListView.hidden = YES;
        _photoListView.desArray = _desArray;
        _photoListView.images = _imageArray;
        
        //计算当前视图为第几张
        for(NSInteger i = 0; i < _imageArray.count;i++){
            NSString *urlNow = _imageArray[i];
            if([_nowImage isEqualToString:urlNow] ){
                _photoListView.indexPath = i;
            }
        }
        [self.window addSubview:_photoListView];
        
        //创建大图显示视图
        _fullImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        _fullImageView.image = self.image;
        _fullImageView.contentMode = UIViewContentModeScaleAspectFit;
        [self.window addSubview:_fullImageView];

    }
}
3、PhotoListView的创建,实现滑动图片浏览

在PhotoListView上创建UIcollectionView,每个cell的大小设置为屏幕大小,每个cell盛放一张图片,滑动方向设置为左右滑动

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(kScreenWidth, kScreenHeight);
layout.minimumInteritemSpacing = 0;
layout.minimumLineSpacing = 30;
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
_collectionView =[[PhotoCollectionView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth + 30,kScreenHeight) collectionViewLayout:layout];
_collectionView.backgroundColor = [UIColor clearColor];
[self addSubview:_collectionView];
此处需要在视图底部创建每张图片的页码和文字提示

//文字显示
_desBg = [[UIView alloc] initWithFrame:CGRectMake(0, kScreenHeight -  85, kScreenWidth, 35)];
_desBg.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
[self addSubview:_desBg];
    
_desLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, kScreenWidth - 20, 35)];
_desLabel.backgroundColor = [UIColor clearColor];
_desLabel.textColor = [UIColor whiteColor];
_desLabel.font = [UIFont systemFontOfSize:13];
_desLabel.textAlignment = NSTextAlignmentLeft;
_desLabel.numberOfLines = 2;
_desLabel.userInteractionEnabled = NO;
[_desBg addSubview:_desLabel];
     
//创建页码显示
_pageCountLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, kScreenHeight -  50, kScreenWidth, 50)];
_pageCountLabel.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
_pageCountLabel.textColor = [UIColor whiteColor];
_pageCountLabel.font = [UIFont systemFontOfSize:15];
_pageCountLabel.textAlignment = NSTextAlignmentCenter;
_pageCountLabel.userInteractionEnabled = NO;
[self addSubview:_pageCountLabel];
滑动时每张图片的页码变化此处我用通知来实现

//接受通知方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(PageChangeAction:) name:@"PageChangeAction" object:nil];
- (void)PageChangeAction:(NSNotification *)text {
    NSString *str = text.userInfo[@"nowPage"];
   _pageCountLabel.text = [NSString stringWithFormat:@"%li/%lu",[str integerValue] + 1,(unsigned long)_images.count];
    if (_descriptionArr.count > 0) {
        NSString *desStr = _descriptionArr[[str integerValue]];
        if ((NSNull *)desStr != [NSNull null] && desStr != nil) {
            _desLabel.text = desStr;
            _desBg.hidden = NO;
        }else{
            _desBg.hidden = YES;
        }
    }else{
        _desBg.hidden = YES;
    }
}
4、子类化UICollectionViewCell,在cell上添加滑动视图UIScollView,用UIScollview盛放图片,用于实现图片的拉伸放大,旋转,保存等功能。

在UICollecionViewCell中添加 PhotoScollView,PhotoScollView继承自UIScolloview,用于放置图片。

//子类化滑动视图
scrollView = [[PhotoScrollView alloc] initWithFrame:self.bounds];    
[self.contentView addSubview:scrollView];

5、PhotoScollView的实现

此处我只添加了单击手势和双击手势,单击是发送通知隐藏滑动视图,双击是放大图片或者缩小图片。因为同时涉及单击和双击,所以要处理单击和双击的冲突。这里的处理方法是双击手势触发时,让单击手势暂时失效 [singleTap requireGestureRecognizerToFail:doubleTap];

- (id)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];
    if (self) {
        self.showsVerticalScrollIndicator = NO;
        self.showsHorizontalScrollIndicator = NO;
        //子视图
        imageView = [[UIImageView alloc] initWithFrame:self.bounds];
        //等比例放大
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        [self addSubview:imageView];

        //指定代理
        self.delegate = self;
        
        //缩放倍数
        self.maximumZoomScale = 3;
        self.minimumZoomScale = .5;

        //双击手势
        UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleTapAction:)];
        
        //设置手指的数量
        doubleTap.numberOfTouchesRequired = 1;
        //点击的数量
        doubleTap.numberOfTapsRequired = 2;
        //将手势添加到滑动视图上
        [self addGestureRecognizer:doubleTap];
        
        //单击手势
        UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTapAction)];
        [self addGestureRecognizer:singleTap];
        
        //双击手势触发时,让单击手势暂时失效
        [singleTap requireGestureRecognizerToFail:doubleTap];
    }
    return self;
}

- (void)setImageUrl:(NSString *)imageUrl{
    
    //填充数据
    //[imageView sd_setImageWithURL:[NSURL URLWithString:imageUrl]];
    imageView.image = [UIImage imageNamed:imageUrl];
}

#pragma mark UITapGestureRecognizer

//单击手势
- (void)singleTapAction{
    
    //发送通知结束浏览
    [[NSNotificationCenter defaultCenter] postNotificationName:@"HideShowViewNotification" object:nil];
    
}

//双击调用的方法
- (void)doubleTapAction:(UITapGestureRecognizer *)tap{
    
    if (self.zoomScale != 1) { //不是正常倍数
        
//        self.zoomScale = 1; //还原
        [self setZoomScale:1 animated:YES];
    }else{
    
//        self.zoomScale = 3;
        [self setZoomScale:3 animated:YES];
    
    }
}

#pragma mark UIScrollViewDelegate
//返回放大的视图
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return imageView;
}
6、 有待完善的地方

放大后的图片和放大前的图片不应该是同一张,放大前应该用缩略图,节约流量,提高显示速度,放大后应该用大图,展示清晰图片。并且真实项目中应该考虑图片缓存等问题。

三、demo链接

CSDN:http://download.csdn.net/detail/fivenineminutes/9715654

github:https://github.com/59minutes/JLImageList



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值