剛好最近在做個商城專案,甲方爸爸說我們們要求不高,你就照著淘寶來就好,額~~~~
好吧,我們就不吐槽了,直接開擼吧,慣例先上一下效果圖
需求以及思路
我們要實現的功能有如下幾個:
- 圖片的全屏檢視以及儲存
- 圖片放大縮小、平移
- 圖片在任何位置的放大檢視,最終都能恢復到原位置,並附帶動效
圖片的放大縮小以及平移功能可以直接通過 UIScrollView 來實現,考慮到複用以及使用場景,所以就直接把功能都封裝在 UIImageView 裡,方便以後直接使用。
程式碼
- 首先建立 LWShowImageView 繼承於UIImageView,在 .m 中建立手勢、新的 UIImageView 以及 UIScrollView ,同時還有幾個重要的引數
@interface LWShowImageView()<UIActionSheetDelegate,UIScrollViewDelegate>
/** 展示手勢*/
@property (nonatomic, strong) UITapGestureRecognizer *showTap;
/** 收起手勢*/
@property (nonatomic, strong) UITapGestureRecognizer *hideTap;
/** 長按手勢*/
@property (nonatomic, strong) UILongPressGestureRecognizer *longTap;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *newImageView;
@implementation LWShowImageView
{
CGRect _oldframe;//原始尺寸
CGRect _newframe;//新尺寸
CGFloat _scale;// 縮放比例
}
-(instancetype)init
{
if (self = [super init]) {
self.userInteractionEnabled = YES;
[self createGesture];
}
return self;
}
/** 建立手勢*/
-(void)createGesture
{
self.showTap= [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(showImageView)];
[self addGestureRecognizer:self.showTap];
self.hideTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideImageView:)];
self.longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(viewLongPress:)];
self.longTap.minimumPressDuration = 1;
}
#pragma mark -- 懶載入
-(UIScrollView *)scrollView
{
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
[_scrollView setBackgroundColor:[UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:1]];
[_scrollView setAlpha:0];
// 縮放級別
_scrollView.minimumZoomScale = 1;
_scrollView.maximumZoomScale = 8;
_scrollView.delegate = self;
// 新增回收手勢
[_scrollView addGestureRecognizer:self.hideTap];
// 新增長按手勢
[_scrollView addGestureRecognizer:self.longTap];
[_scrollView addSubview:self.newImageView];
}
return _scrollView;
}
-(UIImageView *)newImageView
{
if (!_newImageView) {
_newImageView = [[UIImageView alloc] initWithFrame:_oldframe];
[_newImageView setImage:self.image];
_newImageView.contentMode =UIViewContentModeScaleAspectFit;
}
return _newImageView;
}
複製程式碼
- 實現UIScrollViewDelegate ,調整放大後檢視的位置
#pragma MARK-- UIScrollViewDelegate
// 縮放後的檢視
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return self.newImageView;
}
// 調整檢視位置
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
CGRect frame = self.newImageView.frame;
frame.origin.y = (self.scrollView.frame.size.height - self.newImageView.frame.size.height) > 0 ? (self.scrollView.frame.size.height - self.newImageView.frame.size.height) * 0.5 : 0;
frame.origin.x = (self.scrollView.frame.size.width - self.newImageView.frame.size.width) > 0 ? (self.scrollView.frame.size.width - self.newImageView.frame.size.width) * 0.5 : 0;
self.newImageView.frame = frame;
self.scrollView.contentSize = CGSizeMake(self.newImageView.frame.size.width + 30, self.newImageView.frame.size.height + 30);
}
// 縮放比例
-(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(CGFloat)scale
{
_scale = scale;
}
複製程式碼
- 手勢處理,在這裡說明一下,_oldframe 主要是記錄圖片點選放大前的 frame ,在點選圖片後移除原有放大手勢,新增縮小以及長按手勢
/**
* 全屏瀏覽
*/
-(void)showImageView
{
if (!self.image) {
// 圖片還沒有載入完畢
return;
}
// 儲存放大前的frame
_oldframe = [self convertRect:self.bounds toView:[UIApplication sharedApplication].keyWindow];
[[UIApplication sharedApplication].keyWindow addSubview:self.scrollView];
// 移除
[self removeGestureRecognizer:self.showTap];
// 動畫放大所展示的ImageView
[UIView animateWithDuration:0.4 animations:^{
CGFloat y,width,height;
y = ([UIScreen mainScreen].bounds.size.height - self.image.size.height * [UIScreen mainScreen].bounds.size.width / self.image.size.width) * 0.5;
width = [UIScreen mainScreen].bounds.size.width;
height = self.image.size.height * [UIScreen mainScreen].bounds.size.width / self.image.size.width;
_newframe = CGRectMake(0, y, width, height);
[self.newImageView setFrame:_newframe];
[self.scrollView setAlpha:1];
} completion:^(BOOL finished) {
}];
}
/**
* 恢復imageView原始尺寸
*/
- (void)hideImageView:(UITapGestureRecognizer *)tap{
if (_scale > 2.5) {
[self.newImageView setFrame:_newframe];
self.scrollView.contentSize = CGSizeMake(_newframe.size.width + 30, _newframe.size.height + 30);
}
// 恢復
[UIView animateWithDuration:0.4 animations:^{
[self.newImageView setFrame:_oldframe];
[self.scrollView setAlpha:0];
} completion:^(BOOL finished) {
[self addGestureRecognizer:self.showTap];
[self.newImageView removeFromSuperview];
self.newImageView = nil;
[self.scrollView removeFromSuperview];
self.scrollView = nil;
}];
}
/** 長按手勢*/
-(void)viewLongPress:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan) {
UIActionSheet *actionSheet = [[UIActionSheet alloc]initWithTitle:@"儲存圖片" delegate:self cancelButtonTitle:@"取消"destructiveButtonTitle:@"確定" otherButtonTitles:nil];
[actionSheet showInView:self.scrollView];
}
}
複製程式碼
- 圖片儲存
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
// 儲存到相簿
UIImageWriteToSavedPhotosAlbum(self.image, self, @selector(image:didFinishSavingWithError:contextInfo:), (__bridge void *)self);
}
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
NSLog(@"image = %@, error = %@, contextInfo = %@", image, error, contextInfo);
}
複製程式碼
至此,封裝工作全部完成。