// // KTPhotoView.m // Sample // // Created by Kirby Turner on 2/24/10. // Copyright 2010 White Peak Software Inc. All rights reserved. // #import "KTPhotoView.h" #import "KTPhotoScrollViewController.h" #import @interface KTPhotoView (KTPrivateMethods) - (void)loadSubviewsWithFrame:(CGRect)frame; - (BOOL)isZoomed; - (void)toggleChromeDisplay; @end @implementation KTPhotoView @synthesize scroller = scroller_; @synthesize index = index_; - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setDelegate:self]; [self setMaximumZoomScale:5.0]; [self setShowsHorizontalScrollIndicator:NO]; [self setShowsVerticalScrollIndicator:NO]; [self loadSubviewsWithFrame:frame]; //保存图片到相册 UILongPressGestureRecognizer* longPressGes = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(gestureToLongPress:)]; [longPressGes setMinimumPressDuration:0.5]; [self addGestureRecognizer:longPressGes]; } return self; } - (void)loadSubviewsWithFrame:(CGRect)frame { imageView_ = [[UIImageView alloc] initWithFrame:frame]; [imageView_ setContentMode:UIViewContentModeScaleAspectFit]; [self addSubview:imageView_]; } -(void)gestureToLongPress:(UILongPressGestureRecognizer* )ges{//保存图片到相册 switch (ges.state) { case UIGestureRecognizerStateEnded: { } break; case UIGestureRecognizerStateBegan: { // UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil // delegate:self // cancelButtonTitle:NSLocalizedString(@"cancel", nil) // destructiveButtonTitle:NSLocalizedString(@"delete_photo", nil) // otherButtonTitles:NSLocalizedString(@"save_to_photo", nil), nil]; // UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"删除图片" otherButtonTitles:@"保存图片", nil]; // Show the sheet [sheet showInView:self]; } break; default: break; } } - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex{ if(buttonIndex==0){//删除照片 if (self.deleteImageDelegate) { [self.deleteImageDelegate KTPhotoViewDeleteImage:self.index]; } }else if (buttonIndex == 1){//保存图片到相册 UIImageWriteToSavedPhotosAlbum(imageView_.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL); } } - (void)image: (UIImage *) image didFinishSavingWithError: (NSError *) error contextInfo: (void *) contextInfo{//保存图片到相册 if(error != NULL){ //[self makeToast:NSLocalizedString(@"保存图片失败", nil)]; }else{ //[self makeToast:NSLocalizedString(@"保存图片成功", nil)]; } } - (void)setImage:(UIImage *)newImage { [imageView_ setImage:newImage]; } - (void)layoutSubviews { [super layoutSubviews]; if ([self isZoomed] == NO && CGRectEqualToRect([self bounds], [imageView_ frame]) == NO) { [imageView_ setFrame:[self bounds]]; } } - (void)toggleChromeDisplay { if (scroller_) { [scroller_ toggleChromeDisplay]; } } - (BOOL)isZoomed { return !([self zoomScale] == [self minimumZoomScale]); } - (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center { CGRect zoomRect; // the zoom rect is in the content view's coordinates. // At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds. // As the zoom scale decreases, so more content is visible, the size of the rect grows. zoomRect.size.height = [self frame].size.height / scale; zoomRect.size.width = [self frame].size.width / scale; // choose an origin so as to get the right center. zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0); zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0); return zoomRect; } - (void)zoomToLocation:(CGPoint)location { float newScale; CGRect zoomRect; if ([self isZoomed]) { zoomRect = [self bounds]; } else { newScale = [self maximumZoomScale]; zoomRect = [self zoomRectForScale:newScale withCenter:location]; } [self zoomToRect:zoomRect animated:YES]; } - (void)turnOffZoom { if ([self isZoomed]) { [self zoomToLocation:CGPointZero]; } } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if ([touch view] == self) { if ([touch tapCount] == 2) { [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(toggleChromeDisplay) object:nil]; [self zoomToLocation:[touch locationInView:self]]; } } } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch = [touches anyObject]; if ([touch view] == self) { if ([touch tapCount] == 1) { [self performSelector:@selector(toggleChromeDisplay) withObject:nil afterDelay:0.5]; } } } #pragma mark - #pragma mark UIScrollViewDelegate Methods - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { UIView *viewToZoom = imageView_; return viewToZoom; } #pragma mark - #pragma mark Methods called during rotation to preserve the zoomScale and the visible portion of the image - (void)setMaxMinZoomScalesForCurrentBounds { CGSize boundsSize = self.bounds.size; CGSize imageSize = imageView_.bounds.size; // calculate min/max zoomscale CGFloat xScale = boundsSize.width / imageSize.width; // the scale needed to perfectly fit the image width-wise CGFloat yScale = boundsSize.height / imageSize.height; // the scale needed to perfectly fit the image height-wise CGFloat minScale = MIN(xScale, yScale); // use minimum of these to allow the image to become fully visible // on high resolution screens we have double the pixel density, so we will be seeing every pixel if we limit the // maximum zoom scale to 0.5. CGFloat maxScale = 1.0 / [[UIScreen mainScreen] scale]; // don't let minScale exceed maxScale. (If the image is smaller than the screen, we don't want to force it to be zoomed.) if (minScale > maxScale) { minScale = maxScale; } self.maximumZoomScale = maxScale; self.minimumZoomScale = minScale; } // returns the center point, in image coordinate space, to try to restore after rotation. - (CGPoint)pointToCenterAfterRotation { CGPoint boundsCenter = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)); return [self convertPoint:boundsCenter toView:imageView_]; } // returns the zoom scale to attempt to restore after rotation. - (CGFloat)scaleToRestoreAfterRotation { CGFloat contentScale = self.zoomScale; // If we're at the minimum zoom scale, preserve that by returning 0, which will be converted to the minimum // allowable scale when the scale is restored. if (contentScale <= self.minimumZoomScale + FLT_EPSILON) contentScale = 0; return contentScale; } - (CGPoint)maximumContentOffset { CGSize contentSize = self.contentSize; CGSize boundsSize = self.bounds.size; return CGPointMake(contentSize.width - boundsSize.width, contentSize.height - boundsSize.height); } - (CGPoint)minimumContentOffset { return CGPointZero; } // Adjusts content offset and scale to try to preserve the old zoomscale and center. - (void)restoreCenterPoint:(CGPoint)oldCenter scale:(CGFloat)oldScale { // Step 1: restore zoom scale, first making sure it is within the allowable range. self.zoomScale = MIN(self.maximumZoomScale, MAX(self.minimumZoomScale, oldScale)); // Step 2: restore center point, first making sure it is within the allowable range. // 2a: convert our desired center point back to our own coordinate space CGPoint boundsCenter = [self convertPoint:oldCenter fromView:imageView_]; // 2b: calculate the content offset that would yield that center point CGPoint offset = CGPointMake(boundsCenter.x - self.bounds.size.width / 2.0, boundsCenter.y - self.bounds.size.height / 2.0); // 2c: restore offset, adjusted to be within the allowable range CGPoint maxOffset = [self maximumContentOffset]; CGPoint minOffset = [self minimumContentOffset]; offset.x = MAX(minOffset.x, MIN(maxOffset.x, offset.x)); offset.y = MAX(minOffset.y, MIN(maxOffset.y, offset.y)); self.contentOffset = offset; } @end