ios 图片拖拽,捏,双击放大缩小,以及保存到相册
图片拖拽,放大缩小原来是可以不用自己写算法的,直接用UIscrollView即可实现。
保存相册就比较简单了。
比较麻烦的地方:
捏,双击等动作形成的放大、缩小效果需要准确定位。
h文件:
// // DetailPopStarView.h // Gukw // #import <UIKit/UIKit.h> #import "AsyncImageView.h" @interface DetailPopStarView : UIView<UIScrollViewDelegate> @property (nonatomic) NSString *url; @property (nonatomic) AsyncImageView *imgView; @property (nonatomic) CGFloat width; @property (nonatomic) CGFloat height; @property (nonatomic) BOOL isTwiceTaping; @property (nonatomic) BOOL isDoubleTapingForZoom; @property (nonatomic) CGFloat currentScale; @property (nonatomic) CGFloat offsetY; @property (nonatomic) UIScrollView *scrollView; @property (nonatomic) UIActivityIndicatorView *activityIndicatorView; @property (nonatomic) CGFloat touchX; @property (nonatomic) CGFloat touchY; -(void) draw; @end
m文件:
// // DetailPopStarView.m // // #import "DetailPopStarView.h" #import "commonFunctions.h" #define kScreenWidth 320.0 #define kScreenHeight 460.0 #define kMaxZoom 3.0 @implementation DetailPopStarView @synthesize imgView = _imgView; @synthesize url = _url; @synthesize width = _width; @synthesize height = _height; @synthesize activityIndicatorView = _activityIndicatorView; @synthesize isTwiceTaping = _isTwiceTaping; @synthesize scrollView = _scrollView; @synthesize currentScale = _currentScale; @synthesize isDoubleTapingForZoom = _isDoubleTapingForZoom; @synthesize touchX = _touchX; @synthesize touchY = _touchY; @synthesize offsetY = _offsetY; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { // Initialization code } return self; } // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { } - (void) draw{ self.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight); self.backgroundColor = [UIColor blackColor]; self.alpha = 0.0; _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight)]; [self addSubview:_scrollView]; _scrollView.delegate = self; _scrollView.maximumZoomScale = 5.0; CGFloat ratio = _width/_height*kScreenHeight/kScreenWidth; CGFloat min = MIN(ratio, 1.0); _scrollView.minimumZoomScale = min; CGFloat height = _height /_width * kScreenWidth; _imgView = [[AsyncImageView alloc] initWithFrame:CGRectMake(_scrollView.contentOffset.x+100, _scrollView.contentOffset.y+230, 10, 10)]; [_imgView loadImage:_url]; CGFloat y = (kScreenHeight - height)/2.0; _offsetY = 0.0-y; _scrollView.contentSize = CGSizeMake(kScreenWidth, height); [_scrollView addSubview:_imgView]; _scrollView.contentOffset = CGPointMake(0, 0.0-y); [UIView animateWithDuration:0.6 delay:0.0 options: UIViewAnimationCurveEaseOut animations:^{ _imgView.frame = CGRectMake(0, 0, kScreenWidth, height); self.alpha = 1.0; } completion:^(BOOL finished){ } ]; UITapGestureRecognizer *tapImgView = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapImgViewHandle)]; tapImgView.numberOfTapsRequired = 1; tapImgView.numberOfTouchesRequired = 1; [self addGestureRecognizer:tapImgView]; UITapGestureRecognizer *tapImgViewTwice = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapImgViewHandleTwice:)]; tapImgViewTwice.numberOfTapsRequired = 2; tapImgViewTwice.numberOfTouchesRequired = 1; [self addGestureRecognizer:tapImgViewTwice]; [tapImgView requireGestureRecognizerToFail:tapImgViewTwice]; UITapGestureRecognizer *saveTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(saveTapHandler)]; UIButton *save = [commonFunctions generateImage:@"save-pic-button.png" hover:@"save-pic-button-hover.png" withX:245 withY:420]; [save addGestureRecognizer:saveTap]; [self addSubview:save]; _activityIndicatorView = [commonFunctions generateActivityIndicatorView]; [self addSubview:_activityIndicatorView]; } #pragma mark - UIscrollViewDelegate zoom -(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{ _currentScale = scale; NSLog(@"current scale:%f",scale); } -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{ return _imgView; } -(void)scrollViewDidZoom:(UIScrollView *)scrollView{ //当捏或移动时,需要对center重新定义以达到正确显示未知 CGFloat xcenter = scrollView.center.x,ycenter = scrollView.center.y; NSLog(@"adjust position,x:%f,y:%f",xcenter,ycenter); xcenter = scrollView.contentSize.width > scrollView.frame.size.width?scrollView.contentSize.width/2 :xcenter; ycenter = scrollView.contentSize.height > scrollView.frame.size.height ?scrollView.contentSize.height/2 : ycenter; //双击放大时,图片不能越界,否则会出现空白。因此需要对边界值进行限制。 if(_isDoubleTapingForZoom){ NSLog(@"taping center"); xcenter = kMaxZoom*(kScreenWidth - _touchX); ycenter = kMaxZoom*(kScreenHeight - _touchY); if(xcenter > (kMaxZoom - 0.5)*kScreenWidth){//放大后左边超界 xcenter = (kMaxZoom - 0.5)*kScreenWidth; }else if(xcenter <0.5*kScreenWidth){//放大后右边超界 xcenter = 0.5*kScreenWidth; } if(ycenter > (kMaxZoom - 0.5)*kScreenHeight){//放大后左边超界 ycenter = (kMaxZoom - 0.5)*kScreenHeight +_offsetY*kMaxZoom; }else if(ycenter <0.5*kScreenHeight){//放大后右边超界 ycenter = 0.5*kScreenHeight +_offsetY*kMaxZoom; } NSLog(@"adjust postion sucess, x:%f,y:%f",xcenter,ycenter); } [_imgView setCenter:CGPointMake(xcenter, ycenter)]; } #pragma mark - tap -(void)tapImgViewHandle{ NSLog(@"%d",_isTwiceTaping); if(_isTwiceTaping){ return; } NSLog(@"tap once"); [UIView animateWithDuration:0.6 delay:0.0 options: UIViewAnimationCurveEaseOut animations:^{ _imgView.frame = CGRectMake(_scrollView.contentOffset.x+100, _scrollView.contentOffset.y+230, 10, 10); self.alpha = 0.0; } completion:^(BOOL finished){ [self removeFromSuperview]; } ]; } -(IBAction)tapImgViewHandleTwice:(UIGestureRecognizer *)sender{ _touchX = [sender locationInView:sender.view].x; _touchY = [sender locationInView:sender.view].y; if(_isTwiceTaping){ return; } _isTwiceTaping = YES; NSLog(@"tap twice"); if(_currentScale > 1.0){ _currentScale = 1.0; [_scrollView setZoomScale:1.0 animated:YES]; }else{ _isDoubleTapingForZoom = YES; _currentScale = kMaxZoom; [_scrollView setZoomScale:kMaxZoom animated:YES]; } _isDoubleTapingForZoom = NO; //延时做标记判断,使用户点击3次时的单击效果不生效。 [self performSelector:@selector(twiceTaping) withObject:nil afterDelay:0.65]; NSLog(@"sdfdf"); } -(void)twiceTaping{ NSLog(@"no"); _isTwiceTaping = NO; } -(void) saveTapHandler{ if([_activityIndicatorView isAnimating]){ return; } [_activityIndicatorView startAnimating] ; UIImageWriteToSavedPhotosAlbum(_imgView.image, self, @selector(imageSavedToPhotosAlbum: didFinishSavingWithError: contextInfo:), nil); } #pragma mark - savePhotoAlbumDelegate - (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *) contextInfo { NSString *message; NSString *title; [_activityIndicatorView stopAnimating]; if (!error) { title = @"恭喜"; message = @"成功保存到相册"; } else { title = @"失败"; message = [error description]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil]; [alert show]; } @end