博客> 图片浏览
图片浏览
2017-08-17 20:06 评论:0 阅读:75 yangdongming
图片浏览 点击放大

模仿微博/微信 图片浏览中点击放大

(.h文件)

import

@protocol PhotoViewDelegate <NSObject>
-(void)tapHiddenPhotoView;//点击图片时,隐藏图片浏览器
@end

@interface PhotoView : UIView
//当前image
//@property(nonatomic,strong) UIImage *currentImage;
//点击时当前位置的y坐标
@property(nonatomic,assign) CGFloat currentHeight;
//第几张图
@property(nonatomic,assign) NSInteger indexImage;
//父视图
@property(nonatomic,strong)  UIScrollView *scrollView;
//图片视图
@property(nonatomic, strong) UIImageView *imageView;
//代理
@property(nonatomic, assign) id<PhotoViewDelegate> delegate;
//传图片Url
-(id)initWithFrame:(CGRect)frame withPhotoUrl:(NSString *)photoUrl withCurrentframe:                  (CGRect)supFrame isfirst:(BOOL)first;
//传具体图片
-(id)initWithFrame:(CGRect)frame withPhotoImage:(UIImage *)image;

(.m文件)

import "PhotoView.h"

#import "SDWebImageManager.h"
#import "UIImageView+WebCache.h"
#import "MBProgressHUD.h"
#define WIDTH [UIScreen mainScreen].bounds.size.width
#define HEIGHT [UIScreen mainScreen].bounds.size.height
@interface PhotoView ()<UIScrollViewDelegate>{

MBProgressHUD *HUD;
}
@end
@implementation PhotoView
/**网络图片,如果缓存中有会直接到缓存中拿,加载中有加了MBProgressHUD进度条*/
-(id)initWithFrame:(CGRect)frame withPhotoUrl:(NSString *)photoUrl withCurrentframe:    (CGRect)supFrame isfirst:(BOOL)first{
self = [super initWithFrame:frame];

if (self) {

    _currentHeight = CGRectGetMaxY(supFrame);
    //添加图片
    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    BOOL isCached = [manager cachedImageExistsForURL:[NSURL URLWithString:photoUrl]];
    if (!isCached) {//没有缓存

        HUD = [MBProgressHUD showHUDAddedTo:self animated:YES];
        HUD.mode = MBProgressHUDModeDeterminate;
        [self.imageView sd_setImageWithURL:[NSURL URLWithString:photoUrl] placeholderImage:[UIImage imageNamed:@"loading"] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize){  
            HUD.progress = ((float)receivedSize)/expectedSize;
        } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL)        {

// _currentImage = image; if (first) { self.imageView.image = image; self.imageView.frame = supFrame;//图片的原来位置 [UIView animateWithDuration:.3 animations:^{ self.imageView.frame=[self caculateOriginImageSizeWith:image]; }]; } else{

                self.imageView.frame=[self caculateOriginImageSizeWith:image];
            }
            NSLog(@"图片加载完成");

            if (!isCached) {
                [HUD hide:YES];
            }
        }];
    }else{//直接取出缓存的图片,减少流量消耗
        UIImage *cachedImage = [[SDImageCache sharedImageCache] imageFromDiskCacheForKey:photoUrl];

// _currentImage = cachedImage; //第一次进入做的位置变更(放大)动画 if (first) { self.imageView.image = cachedImage; self.imageView.frame = supFrame;//图片的原来位置 [UIView animateWithDuration:.3 animations:^{ self.imageView.frame=[self caculateOriginImageSizeWith:cachedImage]; }]; } else{ self.imageView.frame=[self caculateOriginImageSizeWith:cachedImage]; self.imageView.image=cachedImage; } } } return self; }

/**具体图片,本地图片*/
-(id)initWithFrame:(CGRect)frame withPhotoImage:(UIImage *)image{

self = [super initWithFrame:frame];

if (self) {
    //添加图片
    self.imageView.frame=[self caculateOriginImageSizeWith:image];

    [self.imageView setImage:image];

}
return self;

}

#pragma mark - UIScrollViewDelegate
/**scroll view处理缩放和平移手势,必须需要实现委托下面两个方法,另外 maximumZoomScale和    minimumZoomScale两个属性要不一样*/
//1.返回要缩放的图片
-(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
    return self.imageView;
}

//让图片保持在屏幕中央,防止图片放大时,位置出现跑偏
- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
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;

self.imageView.center = CGPointMake(_scrollView.contentSize.width * 0.5 + offsetX,_scrollView.contentSize.height * 0.5 + offsetY);

}

//2.重新确定缩放完后的缩放倍数
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale{

    [scrollView setZoomScale:scale+0.01 animated:NO];

    [scrollView setZoomScale:scale animated:NO];

}

#pragma mark - 图片的点击,touch事件
//单击
-(void)handleSingleTap:(UITapGestureRecognizer *)gestureRecognizer{
    if (gestureRecognizer.numberOfTapsRequired == 1) {

//         __weak PhotoView *weakSelf = self;
//        
//            CGFloat width = [UIScreen mainScreen].bounds.size.width;
//        
//        [UIView animateWithDuration:.2 animations:^{
//            
//            weakSelf.imageView.image = weakSelf.currentImage;
//            
//            weakSelf.imageView.frame = CGRectMake((width/3) * weakSelf.indexImage+(width/3-60)/2,weakSelf.currentHeight,60, 60);
//        }];

        [self.delegate tapHiddenPhotoView];

    }
}

//双击
-(void)handleDoubleTap:(UITapGestureRecognizer *)gestureRecognizer{

    if (gestureRecognizer.numberOfTapsRequired == 2) {

        if(_scrollView.zoomScale == 1){

            float newScale = [_scrollView zoomScale] *2;

            CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];

            [_scrollView zoomToRect:zoomRect animated:YES];

        }else{

            float newScale = [_scrollView zoomScale]/2;

            CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];

            [_scrollView zoomToRect:zoomRect animated:YES];
        }
    }
}

//2手指操作
-(void)handleTwoFingerTap:(UITapGestureRecognizer *)gestureRecongnizer{

//    float newScale = [_scrollView zoomScale]/2;
//    
//    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecongnizer locationInView:gestureRecongnizer.view]];
//    
//    [_scrollView zoomToRect:zoomRect animated:YES];
}

#pragma mark - 缩放大小获取方法
-(CGRect)zoomRectForScale:(CGFloat)scale withCenter:(CGPoint)center{

    CGRect zoomRect;
    //大小
    zoomRect.size.height = [_scrollView frame].size.height/scale;

    zoomRect.size.width = [_scrollView frame].size.width/scale;
    //原点
    zoomRect.origin.x = center.x - zoomRect.size.width/2;

    zoomRect.origin.y = center.y - zoomRect.size.height/2;

    return zoomRect;
}

#pragma mark - 懒加载

-(UIScrollView *)scrollView{

if (_scrollView==nil) {

    _scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];

    _scrollView.delegate = self;

    _scrollView.minimumZoomScale = 1;

    _scrollView.maximumZoomScale = 3;

    _scrollView.showsHorizontalScrollIndicator = NO;

    _scrollView.showsVerticalScrollIndicator = NO;

    [_scrollView setZoomScale:1];
    //添加scrollView
    [self addSubview:_scrollView];
}
return _scrollView;

}

-(UIImageView *)imageView{

if (_imageView==nil) {

    _imageView = [[UIImageView alloc] init];

    _imageView.contentMode = UIViewContentModeScaleAspectFit;

    _imageView.userInteractionEnabled=YES;
    //添加手势
    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];

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

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

    singleTap.numberOfTapsRequired = 1;

    singleTap.numberOfTouchesRequired = 1;

    doubleTap.numberOfTapsRequired = 2;//需要点两下

    twoFingerTap.numberOfTouchesRequired = 2;//需要两个手指touch

    [_imageView addGestureRecognizer:singleTap];

    [_imageView addGestureRecognizer:doubleTap];

    [_imageView addGestureRecognizer:twoFingerTap];

    [singleTap requireGestureRecognizerToFail:doubleTap];//如果双击了,则不响应单击事件

    [self.scrollView addSubview:_imageView];

}
return _imageView;

}

#pragma mark - 计算图片原始高度,用于高度自适应
-(CGRect)caculateOriginImageSizeWith:(UIImage *)image{

    CGFloat originImageHeight=[self imageCompressForWidth:image targetWidth:WIDTH].size.height;

    if (originImageHeight>=HEIGHT) {

        originImageHeight=HEIGHT;
    }

    CGRect frame=CGRectMake(0, (HEIGHT-originImageHeight)*0.5, WIDTH, originImageHeight);

    return frame;
}

/*指定宽度按比例缩放图片/ -(UIImage ) imageCompressForWidth:(UIImage )sourceImage targetWidth:(CGFloat)defineWidth{

UIImage *newImage = nil;

CGSize imageSize = sourceImage.size;

CGFloat width = imageSize.width;

CGFloat height = imageSize.height;

CGFloat targetWidth = defineWidth;

CGFloat targetHeight = height / (width / targetWidth);

CGSize size = CGSizeMake(targetWidth, targetHeight);

CGFloat scaleFactor = 0.0;

CGFloat scaledWidth = targetWidth;

CGFloat scaledHeight = targetHeight;

CGPoint thumbnailPoint = CGPointMake(0.0, 0.0);

if(CGSizeEqualToSize(imageSize, size) == NO){

    CGFloat widthFactor = targetWidth / width;

    CGFloat heightFactor = targetHeight / height;

    if(widthFactor > heightFactor){

        scaleFactor = widthFactor;

    }else{

        scaleFactor = heightFactor;
    }
    scaledWidth = width * scaleFactor;

    scaledHeight = height * scaleFactor;

    if(widthFactor > heightFactor){

        thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;

    }else if(widthFactor < heightFactor xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed>

//跳转方式。目前做的是URL及缓存图片 加载本地图片未完善动画及坐标处理 typedef NS_ENUM(NSUInteger,PhotoBroswerVCType) {

//modal 未做动画及坐标处理(可自己做修改)
PhotoBroswerVCTypePush=0,

//push 未完善(可根据自己做修改)
PhotoBroswerVCTypeModal,

//zoom 完善
PhotoBroswerVCTypeZoom,

};

@interface ImageBrowserViewController : UIViewController //显示图片 +(void)show:(UIViewController )handleVC type:(PhotoBroswerVCType)type index:(NSUInteger)index currentFrame:(CGRect)frame statu:(NSArray )status imagesBlock:(NSArray *(^)())imagesBlock; @end

(.m)

import "ImageBrowserViewController.h"

#import "PhotoView.h"
#define WIDTH [UIScreen mainScreen].bounds.size.width
#define HEIGHT [UIScreen mainScreen].bounds.size.height
@interface ImageBrowserViewController ()<UIScrollViewDelegate>{

NSMutableArray *_subViewArray;//scrollView的所有子视图   
}
//第n张是否有
@property(nonatomic,strong) NSArray *ImageVstaus;
//第一次进来
@property(nonatomic,assign) BOOL isFirst;
//相对坐标
@property(nonatomic,assign) CGRect currentRectframe;
//背景容器视图
@property(nonatomic,strong) UIScrollView *scrollView;
//外部操作控制器
@property (nonatomic,weak) UIViewController *handleVC;
//图片浏览方式
@property (nonatomic,assign) PhotoBroswerVCType type;
//图片数组
@property (nonatomic,strong) NSArray *imagesArray;
//初始显示的index  点击的位置
@property (nonatomic,assign) NSUInteger index;
//分页
@property(nonatomic,strong) UIPageControl *pageControl;
//图片
@property(nonatomic,strong) PhotoView *photoView;

@end

@implementation ImageBrowserViewController

-(instancetype)init{

    self=[super init];
    if (self) {
        _subViewArray = [NSMutableArray arrayWithCapacity:0];
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.view.backgroundColor=[UIColor blackColor];

    //去除自动处理
    self.automaticallyAdjustsScrollViewInsets = NO;

    //设置contentSize
    self.scrollView.contentSize = CGSizeMake(WIDTH * self.imagesArray.count, 0);

    for (int i = 0; i < self xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed>=self.imagesArray.count) {

                offsetIndex = self.index-1;
            }
            else{
                offsetIndex = self.index;
            }
        }
        else if (![_ImageVstaus[0] boolValue]&&self.imagesArray.count==1&&![_ImageVstaus[2] boolValue])
        {
            offsetIndex = self.index - 1;
        }
        else{

        offsetIndex = self.index;

        }

    }

self.scrollView.contentOffset = CGPointMake(WIDTH*offsetIndex, 0);//此句代码需放在[_subViewArray addObject:[NSNull class]]之后,因为其主动调用scrollView的代理方法,否则会出现数组越界
//控制分页pageControl的选中页面   (用是否有图片去判断)
if (self.imagesArray.count==1) {

    _pageControl.hidden=YES;

}else{
    if (![_ImageVstaus[0] boolValue]&&self.imagesArray.count == 2) {

        self.pageControl.currentPage = self.index - 1;

    }
    else{

        if([_ImageVstaus[0] boolValue]&&self.imagesArray.count == 2 && [_ImageVstaus[2] boolValue]){

            if (self.index>=self.imagesArray.count) {

                self.pageControl.currentPage = self.index-1;
            }
            else{
                self.pageControl.currentPage = self.index;
            }
        }
        else{

            self.pageControl.currentPage=self.index;
        }

    }
}

[self loadPhote:offsetIndex];//显示当前索引的图片

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

[self.view addGestureRecognizer:tap];//为当前view添加手势,隐藏当前显示窗口

}

-(void)hideCurrentVC:(UIGestureRecognizer *)tap{

[self hideScanImageVC];

}

pragma mark - 显示图片

-(void)loadPhote:(NSInteger)index{

// NSInteger imagItemIndex = index; //
if (index<0>=self.imagesArray.count) { // // if(index >=self.imagesArray.count){ //
// while (imagItemIndex>=self.imagesArray.count) {

// if (imagItemIndex>=1) {

// imagItemIndex = imagItemIndex -1; // } // // } //
// } // else{ return; } // } // if (index==1&&self.imagesArray.count==2&&!_isneedFirst) { //
// imagItemIndex = imagItemIndex - 1; // // }

id currentPhotoView = [_subViewArray objectAtIndex:index];

if (![currentPhotoView isKindOfClass:[PhotoView class]]) {
    //url数组或图片数组
    CGRect frame = CGRectMake(index*_scrollView.frame.size.width, 0, self.view.frame.size.width, self.view.frame.size.height);

    if ([[self.imagesArray firstObject] isKindOfClass:[UIImage class]]) {

        PhotoView *photoV = [[PhotoView alloc] initWithFrame:frame withPhotoImage:[self.imagesArray objectAtIndex:index]];

        photoV.delegate = self;

        [self.scrollView insertSubview:photoV atIndex:0];

        [_subViewArray replaceObjectAtIndex:index withObject:photoV];

        self.photoView=photoV;

    }else if ([[self.imagesArray firstObject] isKindOfClass:[NSString class]]){

        PhotoView *photoV = [[PhotoView alloc] initWithFrame:frame withPhotoUrl:[self.imagesArray objectAtIndex:index] withCurrentframe:_currentRectframe isfirst:!_isFirst];

        photoV.delegate = self;

        photoV.indexImage = index;

        [self.scrollView insertSubview:photoV atIndex:0];

        [_subViewArray replaceObjectAtIndex:index withObject:photoV];

        self.photoView=photoV;
    }
    _isFirst= YES;
}

}

#pragma mark - 生成显示窗口
+(void)show:(UIViewController *)handleVC type:(PhotoBroswerVCType)type index:(NSUInteger)index currentFrame:(CGRect)frame statu:(NSArray *)status imagesBlock:(NSArray *(^)())imagesBlock{

    NSArray *photoModels = imagesBlock();//取出相册数组

    if(photoModels == nil || photoModels.count == 0) {
        return;
}

ImageBrowserViewController *imgBrowserVC = [[self alloc] init];

imgBrowserVC.currentRectframe = frame;

// if(index >= photoModels.count){ // return; // }

NSInteger imagItemIndex = index;

if (index >=photoModels.count) {

    if(index >=photoModels.count){

        while (imagItemIndex>=photoModels.count) {
            if (imagItemIndex>=1) {
                imagItemIndex = imagItemIndex -1;
            }

        }

    }
    else{
        return;
    }
}

imgBrowserVC.ImageVstaus = status;

imgBrowserVC.index = index;

imgBrowserVC.imagesArray = photoModels;

imgBrowserVC.type =type;

imgBrowserVC.handleVC = handleVC;

[imgBrowserVC show]; //展示

}

/* 真正展示 / -(void)show{

switch (_type) {

    case PhotoBroswerVCTypePush://push

        [self pushPhotoVC];

        break;

    case PhotoBroswerVCTypeModal://modal

        [self modalPhotoVC];

        break;

    case PhotoBroswerVCTypeZoom://zoom
    {
        __weak ImageBrowserViewController *weakSelf = self;

        self.view.frame = [UIScreen mainScreen].bounds;

        [weakSelf zoomPhotoVC];

        break;
    }

    default:
        break;
}

}

/* push / -(void)pushPhotoVC{

[_handleVC.navigationController pushViewController:self animated:YES];

}

/* modal / -(void)modalPhotoVC{

[_handleVC presentViewController:self animated:YES completion:nil];

}

/* zoom / -(void)zoomPhotoVC{

//拿到window
UIWindow *window = _handleVC.view.window;

if(window == nil){

    NSLog(@"错误:窗口为空!");

    return;
}

self.view.frame=[UIScreen mainScreen].bounds;

[window addSubview:self.view]; //添加视图

[_handleVC addChildViewController:self]; //添加子控制器

}

pragma mark - 隐藏当前显示窗口

-(void)hideScanImageVC{

switch (_type) {
    case PhotoBroswerVCTypePush://push

        [self.navigationController popViewControllerAnimated:YES];

        break;

    case PhotoBroswerVCTypeModal://modal

        [self dismissViewControllerAnimated:YES completion:NULL];

        break;

    case PhotoBroswerVCTypeZoom://zoom

        [self.view removeFromSuperview];

        [self removeFromParentViewController];

        break;

    default:
        break;
}

}

pragma mark - UIScrollViewDelegate

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

CGFloat pageWidth = scrollView.frame.size.width;

NSInteger page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;

if (page<0>=self.imagesArray.count) {

    return;
}

self.pageControl.currentPage = page;

for (UIView *view in scrollView.subviews) {

    if ([view isKindOfClass:[PhotoView class]]) {

        PhotoView *photoV=(PhotoView *)[_subViewArray objectAtIndex:page];

        if (photoV!=self.photoView) {

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

            self.photoView=photoV;
        }
    }
}

[self loadPhote:page];

}

pragma mark - PhotoViewDelegate

-(void)tapHiddenPhotoView{

[self hideScanImageVC];//隐藏当前显示窗口

}

pragma mark - 懒加载

-(UIScrollView *)scrollView{

if (_scrollView==nil) {

    _scrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, WIDTH, HEIGHT)];

    _scrollView.delegate=self;

    _scrollView.pagingEnabled=YES;

    _scrollView.contentOffset=CGPointZero;
    //设置最大伸缩比例
    _scrollView.maximumZoomScale=3;
    //设置最小伸缩比例
    _scrollView.minimumZoomScale=1;

    _scrollView.showsHorizontalScrollIndicator = NO;

    _scrollView.showsVerticalScrollIndicator = NO;

    [self.view addSubview:_scrollView];
}
return _scrollView;

}

-(UIPageControl *)pageControl{

if (_pageControl==nil) {

    UIView *bottomView=[[UIView alloc] initWithFrame:CGRectMake(0, HEIGHT-40, WIDTH, 30)];

    bottomView.backgroundColor=[UIColor clearColor];

    _pageControl = [[UIPageControl alloc] initWithFrame:bottomView.bounds];

    _pageControl.currentPage = self.index;

    _pageControl.numberOfPages = self.imagesArray.count;

    _pageControl.currentPageIndicatorTintColor = [UIColor colorWithRed:235 green:235 blue:235 alpha:0.6];

    _pageControl.pageIndicatorTintColor = [UIColor grayColor];

    [bottomView addSubview:_pageControl];

    [self.view addSubview:bottomView];
}
return _pageControl;

}

有用得到的地方可以自己去做修改

收藏
1
sina weixin mail 回到顶部