这次的封装,最终效果就是可以滑动查看所有图片,单击返回、双击放大/缩小、捏合放大/缩小的手势。在此,封装了三个类。如下所示:
第一个类(我们直接要使用的类):
#import "ImageScanCell.h"
@interface ImageScanController : BaseController
//1.图片数组 (一组图片, 是给collectionView现实的)
@property(nonatomic, strong)NSArray * imageURLStringArray;
//2.当前是 哪个item被点击,就显示哪个item的图片
//如何得知哪个item'被点击, 传递 当前item的索引位置
@property(nonatomic, strong)NSIndexPath * selectedIndexPath;
@property (nonatomic,assign) NSInteger currentPage;
@end
#import "ImageScanController.h"
@interface ImageScanController ()<UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
{
//子视图
UICollectionView * _collectionView;
//取非
BOOL _isHidden;
// 需要下载的图片
UIImage * _myImage;
UIPageControl *_page;
}
@end
static NSString * imageScanID = @"ImageScanCell";
@implementation ImageScanController
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"图片浏览";
self.view.backgroundColor = [UIColor whiteColor];
//创建子视图
[self _loadSubViews];
//创建 下载的按钮
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setImage:[UIImage imageNamed:@"img_download_p"] forState:UIControlStateNormal];
[button addTarget:self action:@selector(downloadImageAction:) forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(kScreenWidth - 60 - 20, kScreenHeight - 60 - 64 - 30, 60, 60);
[self.view addSubview:button];
//注册成为kNavigationBarHideOrNot这条通知的观察者
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(hideNavigationOrNot:) name:@"HideOrNot" object:nil];
}
#pragma mark - button action
- (void)downloadImageAction:(UIButton *)sender{
//实现下载 图片 到相册 (保存)
//C语言有一个函数
//参数一:要保存哪张图片
//参数二:回调目标, 当这个函数走完之后,会由 哪个对象(当前这个参数), 去调用一个什么方法(后面参数三的方法)
//参数三:@selector 方法签名, 是要被调用的方法的名字(文档中有给定的方法)
//参数四:指 要传递的信息,一般是NULL
//回调方法注意看文档。
UIImageWriteToSavedPhotosAlbum(_myImage, self, @selector(image: didFinishSavingWithError:contextInfo:), NULL);
}
- (void) image: (UIImage *) image
didFinishSavingWithError: (NSError *) error
contextInfo: (void *) contextInfo{
//根据不同的 情况,让 提示视图 的 提示消息显示不同的内容。
NSString * message = nil;
if (error == nil ) {
message = @"保存成功";
} else{
message = @"保存失败";
}
// 创建提示视图, 通知用户是否保存成功
UIAlertView * alertView = [[UIAlertView alloc]initWithTitle:@"提示" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alertView show];
}
#pragma mark - notification Action
- (void)hideNavigationOrNot:(NSNotification *)notification{
_isHidden = !_isHidden;
// 隐藏 、 显示导航栏
[self.navigationController setNavigationBarHidden:_isHidden animated:YES];
[self dismissViewControllerAnimated:NO completion:nil];
}
#pragma mark - remove observer
- (void)dealloc{
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"HideOrNot" object:nil];
}
#pragma mark - private action
- (void)_loadSubViews{
//创建布局对象
UICollectionViewFlowLayout * flow = [[UICollectionViewFlowLayout alloc]init];
flow.itemSize = CGSizeMake(kScreenWidth, kScreenHeight);
flow.minimumLineSpacing = 0;
flow.minimumInteritemSpacing = 0;
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//创建collectionView
_collectionView = [[UICollectionView alloc]initWithFrame:[UIScreen mainScreen].bounds collectionViewLayout:flow];
_collectionView.dataSource = self;
_collectionView.delegate = self;
_collectionView.pagingEnabled = YES;
[self.view addSubview:_collectionView];
//注册单元格
[_collectionView registerClass:[ImageScanCell class] forCellWithReuseIdentifier:imageScanID];
UIPageControl *page = [[UIPageControl alloc] initWithFrame:CGRectMake((self.view.frame.size.width-150)/2, self.view.frame.size.height-20, 150, 20)];
page.numberOfPages = self.imageURLStringArray.count;
page.backgroundColor = [UIColor clearColor];
page.currentPageIndicatorTintColor = [UIColor whiteColor];
page.pageIndicatorTintColor = [UIColor grayColor];
[self.view addSubview:page];
page.currentPage = self.currentPage;
_page = page;
}
- (void)setImageURLStringArray:(NSArray *)imageURLStringArray{
if (_imageURLStringArray != imageURLStringArray) {
_imageURLStringArray = imageURLStringArray;
}
//[self _loadSubViews];
}
- (void)setSelectedIndexPath:(NSIndexPath *)selectedIndexPath{
if (_selectedIndexPath != selectedIndexPath) {
_selectedIndexPath = selectedIndexPath;
}
}
#pragma mark - collection view data source
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return _imageURLStringArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
//创建单元格
ImageScanCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:imageScanID forIndexPath:indexPath];
//cell.backgroundColor = [UIColor redColor];
//传数据
cell.imageURLString = _imageURLStringArray[indexPath.row];
return cell;
}
//点击放大然后滑倒其他界面后, 让原本的界面上的图片变小
//结束 在界面显示的单元格的索引
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
//NSLog(@"当前是第%ld个图片", indexPath.row);
//判断这个 方法中的 indexPath所 对应的 这个 滑动视图(图片), 是否有被放大
//拿到 indexPath所对应的 单元格 上面的 滑动视图
//根据参数 拿到这个单元格
ImageScanCell * scanCell = (ImageScanCell *) cell;
// if ( scanCell.imageScrollView.zoomScale > 1) {
//
// [scanCell.imageScrollView setZoomScale:1.0 animated:YES];
// }else if(scanCell.imageScrollView.zoomScale < 1) {
//
[scanCell.imageScrollView setZoomScale:1.0 animated:YES];
// }
}
//将要展示单元格 是哪个, 索引位置
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
//拿到当前显示的单元格对象
ImageScanCell * myCell = (ImageScanCell *)cell;
//拿到当前单元格显示的 图片
_myImage = myCell.imageScrollView.imgView.image;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSInteger pageCurrent = scrollView.contentOffset.x/kScreenWidth;
_page.currentPage = pageCurrent;
}
#pragma mark - view life cycle
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
//视图将要出现, collectionView 是view子视图,我也要出现了,
//本来是出现第0个索引位置的单元格
//我们复写这个方法,改变 它 当前即将要现实的单元格
//我们指定让collectionView滑动到 指定位置的单元格
//参数一:指定的 单元格索引
//参数二:滑动停止后的 视图显示位置(枚举值)
[_collectionView scrollToItemAtIndexPath:_selectedIndexPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally
animated:YES];
}
第二个类:--------------------------------------------------------
#import <UIKit/UIKit.h>
@interface ScrollImageView : UIScrollView<UIScrollViewDelegate>
//1.子视图
@property(nonatomic, strong)UIImageView * imgView;
//2.显示数据
@property(nonatomic, copy)NSString * imageURLString;
@end
#import "ScrollImageView.h"
@implementation ScrollImageView
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
//加载子视图
_imgView = [[UIImageView alloc]initWithFrame:[UIScreen mainScreen].bounds];
/**
UIViewContentModeScaleToFill,
UIViewContentModeRedraw,
};
*/
_imgView.contentMode = UIViewContentModeScaleToFill;
//用户响应时间
_imgView.userInteractionEnabled = YES;
// _imgView.backgroundColor = [UIColor yellowColor];
[self addSubview:_imgView];
//自己的属性设置
self.minimumZoomScale = 0.5;
self.maximumZoomScale = 3.0;
//设置代理(自己成为自己的代理,来实现缩放功能)
self.delegate = self;
//添加手势
UITapGestureRecognizer * tapOnce = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(hidesOrNotAction:)];
tapOnce.numberOfTapsRequired = 1; //默认是1,所以这行代码可省
//添加到滑动视图上面(先把 imageView的 用户交互事件打开)
[self addGestureRecognizer:tapOnce];
//双击手势
UITapGestureRecognizer * doubleTap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(doubleTapAction:)];
doubleTap.numberOfTapsRequired = 2;
[self addGestureRecognizer:doubleTap];
//这个方法是为了 防止 两个手势的冲突, 当双击的时候,会冲突单击的方法,
//让冲突的手势 不响应
//当我们单击的时候,让双击不响应
[tapOnce requireGestureRecognizerToFail:doubleTap];
}
return self;
}
- (void)setImageURLString:(NSString *)imageURLString{
if (_imageURLString != imageURLString) {
_imageURLString = imageURLString;
}
//赋值(图片)
[_imgView setImageWithURL:[NSURL URLWithString:_imageURLString]];
// 安全判断,如果没有图片的话,加载默认的图片
if (!_imgView.image) {
_imgView.image = [UIImage imageNamed:@"default_image.png"];
}
}
#pragma mark - tap action
//隐藏导航栏
// 当前我们是在 滑动视图这个视图类中,,没有导航控制器
//导航控制器 --》 控制器容器
- (void)hidesOrNotAction:(UITapGestureRecognizer *)tap {
//发通知 告诉 imageScanController ,你要隐藏 或者是显示 导航栏
[[NSNotificationCenter defaultCenter] postNotificationName:@"HideOrNot" object:nil];
}
//双击实现放大或者缩小
- (void)doubleTapAction:(UITapGestureRecognizer *)tap{
if (self.zoomScale > 1) {
[self setZoomScale:1.0 animated:NO];
} else{
[self setZoomScale:2.0 animated:NO];
}
}
#pragma mark - delegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{
return _imgView;
}
第三个类:----------------------------------------------------------------
#import <UIKit/UIKit.h>
#import "ScrollImageView.h"
@interface ImageScanCell : UICollectionViewCell
//子视图(自己封装的滑动视图)
//测试界面效果,我们先给一个imageView
@property(nonatomic, strong)ScrollImageView * imageScrollView;
//数据
@property(nonatomic, copy)NSString * imageURLString;
@end
#import "ImageScanCell.h"
@implementation ImageScanCell
//代码方式
- (id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
//加载子视图
_imageScrollView = [[ScrollImageView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)];
_imageScrollView.pagingEnabled = NO;
//_imageScrollView.backgroundColor = [UIColor greenColor];
[self.contentView addSubview:_imageScrollView];
}
return self;
}
- (void)setImageURLString:(NSString *)imageURLString{
if (_imageURLString != imageURLString) {
_imageURLString = imageURLString;
}
//传递数据 给 滑动视图
_imageScrollView.imageURLString = _imageURLString;
}