| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- //
- // ZLPhotoPickerBrowserPhotoScrollView.m
- // ZLAssetsPickerDemo
- //
- //
- #import "DKPhotoPickerBrowserPhotoScrollView.h"
- #import "DKPhotoPickerDatas.h"
- #import "UIImageView+WebCache.h"
- #import "DACircularProgressView.h"
- #import "DKPhotoPickerCommon.h"
- // Private methods and properties
- @interface DKPhotoPickerBrowserPhotoScrollView ()<UIActionSheetDelegate> {
- DKPhotoPickerBrowserPhotoView *_tapView; // for background taps
- DKPhotoPickerBrowserPhotoImageView *_photoImageView;
- }
- @property (assign,nonatomic) CGFloat progress;
- @property (strong,nonatomic) DACircularProgressView *progressView;
- @end
- @implementation DKPhotoPickerBrowserPhotoScrollView
- - (DACircularProgressView *)progressView{
- if (!_progressView) {
- DACircularProgressView *progressView = [[DACircularProgressView alloc] init];
-
- progressView.frame = CGRectMake(0, 0, ZLPickerProgressViewW, ZLPickerProgressViewH);
- progressView.center = CGPointMake([UIScreen mainScreen].bounds.size.width * 0.5, [UIScreen mainScreen].bounds.size.height * 0.5);
- progressView.roundedCorners = YES;
- if (iOS7gt) {
- progressView.thicknessRatio = 0.1;
- progressView.roundedCorners = NO;
- } else {
- progressView.thicknessRatio = 0.2;
- progressView.roundedCorners = YES;
- }
-
- [self addSubview:progressView];
- self.progressView = progressView;
- }
- return _progressView;
- }
- - (id)init{
- if ((self = [super init])) {
-
- // Setup
- // Tap view for background
- _tapView = [[DKPhotoPickerBrowserPhotoView alloc] initWithFrame:self.bounds];
- _tapView.tapDelegate = self;
- _tapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- _tapView.backgroundColor = [UIColor blackColor];
- [self addSubview:_tapView];
-
- // Image view
- _photoImageView = [[DKPhotoPickerBrowserPhotoImageView alloc] initWithFrame:CGRectZero];
- _photoImageView.tapDelegate = self;
- _photoImageView.contentMode = UIViewContentModeCenter;
- _photoImageView.backgroundColor = [UIColor blackColor];
- [self addSubview:_photoImageView];
-
- // Setup
- self.backgroundColor = [UIColor blackColor];
- self.delegate = self;
- self.showsHorizontalScrollIndicator = NO;
- self.showsVerticalScrollIndicator = NO;
- self.decelerationRate = UIScrollViewDecelerationRateFast;
- self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
- UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longGesture:)];
- [self addGestureRecognizer:longGesture];
-
- }
- return self;
- }
- - (void)longGesture:(UILongPressGestureRecognizer *)gesture{
- if (gesture.state == UIGestureRecognizerStateBegan) {
-
- if (!self.sheet) {
- self.sheet = [[UIActionSheet alloc] initWithTitle:@"提示" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"保存到相册" otherButtonTitles:nil, nil];
- }
- [self.sheet showInView:self];
- }
- }
- - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
- if (buttonIndex == 0){
- UIImageWriteToSavedPhotosAlbum(_photoImageView.image, nil, nil, nil);
- }
- }
- - (void)dealloc {
- [[NSNotificationCenter defaultCenter] removeObserver:self];
- }
- - (void)setPhoto:(DKPhotoPickerBrowserPhoto *)photo{
- _photo = photo;
-
- __weak typeof(self) weakSelf = self;
- if (photo.photoURL.absoluteString.length) {
- // 本地相册
- NSRange photoRange = [photo.photoURL.absoluteString rangeOfString:@"assets-library"];
- if (photoRange.location != NSNotFound){
- [[DKPhotoPickerDatas defaultPicker] getAssetsPhotoWithURLs:photo.photoURL callBack:^(UIImage *obj) {
- _photoImageView.image = obj;
- [weakSelf displayImage];
- }];
- }else{
- UIImage *thumbImage = photo.thumbImage;
- if (thumbImage == nil) {
- thumbImage = _photoImageView.image;
- }else{
- _photoImageView.image = thumbImage;
- }
-
- _photoImageView.contentMode = UIViewContentModeScaleAspectFit;
- _photoImageView.frame = [self setMaxMinZoomScalesForCurrentBounds:_photoImageView];
-
- // 网络URL
- [_photoImageView sd_setImageWithURL:photo.photoURL placeholderImage:thumbImage options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) {
- _photoImageView.progress = (double)receivedSize / expectedSize;
- } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
- _photoImageView.image = image;
- [weakSelf displayImage];
- }];
-
- }
-
-
- } else if (photo.photoImage){
- _photoImageView.image = photo.photoImage;
- [self displayImage];
- }
-
- }
- - (CGRect )setMaxMinZoomScalesForCurrentBounds:(UIImageView *)imageView {
- // Sizes
- CGSize boundsSize = [UIScreen mainScreen].bounds.size;
- CGSize imageSize = imageView.image.size;
- if (imageSize.width == 0 && imageSize.height == 0) {
- return imageView.frame;
- }
-
- 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
- // Image is smaller than screen so no zooming!
- if (xScale >= 1 && yScale >= 1) {
- minScale = MIN(xScale, yScale);
- }
-
- CGRect frameToCenter = CGRectMake(0, 0, imageSize.width * minScale, imageSize.height * minScale);
-
- // Horizontally
- if (frameToCenter.size.width < boundsSize.width) {
- frameToCenter.origin.x = floorf((boundsSize.width - frameToCenter.size.width) / 2.0);
- } else {
- frameToCenter.origin.x = 0;
- }
-
- // Vertically
- if (frameToCenter.size.height < boundsSize.height) {
- frameToCenter.origin.y = floorf((boundsSize.height - frameToCenter.size.height) / 2.0);
- } else {
- frameToCenter.origin.y = 0;
- }
-
- return frameToCenter;
- }
- #pragma mark - setProgress
- - (void)setProgress:(CGFloat)progress{
- _progress = progress;
-
- if (progress == 0) return ;
- if (progress / 1.0 != 1.0) {
- [self.progressView setProgress:progress animated:YES];
- }else{
- [self.progressView removeFromSuperview];
- self.progressView = nil;
- }
- }
- #pragma mark - Image
- // Get and display image
- - (void)displayImage {
- // Reset
- self.maximumZoomScale = 1;
- self.minimumZoomScale = 1;
- self.zoomScale = 1;
- self.contentSize = CGSizeMake(0, 0);
-
- // Get image from browser as it handles ordering of fetching
- UIImage *img = _photoImageView.image;
- if (img) {
-
- // Set image
- _photoImageView.image = img;
- _photoImageView.hidden = NO;
-
- // Setup photo frame
- CGRect photoImageViewFrame;
- photoImageViewFrame.origin = CGPointZero;
- photoImageViewFrame.size = img.size;
- _photoImageView.frame = photoImageViewFrame;
- self.contentSize = photoImageViewFrame.size;
-
- // Set zoom to minimum zoom
- [self setMaxMinZoomScalesForCurrentBounds];
-
- }
- [self setNeedsLayout];
- }
- #pragma mark - Loading Progress
- #pragma mark - Setup
- - (CGFloat)initialZoomScaleWithMinScale {
- CGFloat zoomScale = self.minimumZoomScale;
- if (_photoImageView) {
- // Zoom image to fill if the aspect ratios are fairly similar
- CGSize boundsSize = self.bounds.size;
- CGSize imageSize = _photoImageView.image.size;
- CGFloat boundsAR = boundsSize.width / boundsSize.height;
- CGFloat imageAR = imageSize.width / imageSize.height;
- CGFloat xScale = boundsSize.width / imageSize.width;
- if (ABS(boundsAR - imageAR) < 0.17) {
- zoomScale = xScale;
- }
- }
- return zoomScale;
- }
- - (void)setMaxMinZoomScalesForCurrentBounds {
-
- // Reset
- self.maximumZoomScale = 1;
- self.minimumZoomScale = 1;
- self.zoomScale = 1;
-
- // Bail if no image
- if (_photoImageView.image == nil) return;
-
- // Reset position
- _photoImageView.frame = CGRectMake(0, 0, _photoImageView.frame.size.width, _photoImageView.frame.size.height);
-
- // Sizes
- CGSize boundsSize = self.bounds.size;
- CGSize imageSize = _photoImageView.image.size;
-
- // Calculate Min
- 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
-
- // Calculate Max
- CGFloat maxScale = 3;
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
- // Let them go a bit bigger on a bigger screen!
- maxScale = 4;
- }
-
- // Image is smaller than screen so no zooming!
- if (xScale >= 1 && yScale >= 1) {
- minScale = MIN(xScale, yScale);
- }
-
- // Set min/max zoom
- self.maximumZoomScale = maxScale;
- self.minimumZoomScale = minScale;
-
- // Initial zoom
- self.zoomScale = [self initialZoomScaleWithMinScale];
-
- // If we're zooming to fill then centralise
- if (self.zoomScale != minScale) {
- // Centralise
- self.contentOffset = CGPointMake((imageSize.width * self.zoomScale - boundsSize.width) / 2.0,
- (imageSize.height * self.zoomScale - boundsSize.height) / 2.0);
- // Disable scrolling initially until the first pinch to fix issues with swiping on an initally zoomed in photo
- self.scrollEnabled = NO;
- }
-
- // Layout
- [self setNeedsLayout];
-
- }
- #pragma mark - Layout
- - (void)layoutSubviews {
- // Super
- [super layoutSubviews];
-
- // Center the image as it becomes smaller than the size of the screen
- CGSize boundsSize = self.bounds.size;
- CGRect frameToCenter = _photoImageView.frame;
-
- // Horizontally
- if (frameToCenter.size.width < boundsSize.width) {
- frameToCenter.origin.x = floorf((boundsSize.width - frameToCenter.size.width) / 2.0);
- } else {
- frameToCenter.origin.x = 0;
- }
-
- // Vertically
- if (frameToCenter.size.height < boundsSize.height) {
- frameToCenter.origin.y = floorf((boundsSize.height - frameToCenter.size.height) / 2.0);
- } else {
- frameToCenter.origin.y = 0;
- }
-
- // Center
- if (!CGRectEqualToRect(_photoImageView.frame, frameToCenter))
- _photoImageView.frame = frameToCenter;
-
- }
- #pragma mark - UIScrollViewDelegate
- - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
- return _photoImageView;
- }
- - (void)scrollViewDidZoom:(UIScrollView *)scrollView {
- [self setNeedsLayout];
- [self layoutIfNeeded];
- }
- #pragma mark - Tap Detection
- - (void)handleDoubleTap:(CGPoint)touchPoint {
-
- // Zoom
- if (self.zoomScale != self.minimumZoomScale && self.zoomScale != [self initialZoomScaleWithMinScale]) {
-
- // Zoom out
- [self setZoomScale:self.minimumZoomScale animated:YES];
- self.contentSize = CGSizeMake(self.frame.size.width, 0);
- } else {
-
- // Zoom in to twice the size
- CGFloat newZoomScale = ((self.maximumZoomScale + self.minimumZoomScale) / 2);
- CGFloat xsize = self.bounds.size.width / newZoomScale;
- CGFloat ysize = self.bounds.size.height / newZoomScale;
- [self zoomToRect:CGRectMake(touchPoint.x - xsize/2, touchPoint.y - ysize/2, xsize, ysize) animated:YES];
-
- }
-
- }
- - (void)imageView:(UIImageView *)imageView singleTapDetected:(UITouch *)touch{
- [self disMissTap:nil];
- }
- #pragma mark - disMissTap
- - (void) disMissTap:(UITapGestureRecognizer *)tap{
- if (self.callback){
- self.callback(nil);
- }else if ([self.photoScrollViewDelegate respondsToSelector:@selector(pickerPhotoScrollViewDidSingleClick:)]) {
- [self.photoScrollViewDelegate pickerPhotoScrollViewDidSingleClick:self];
- }
- }
- // Image View
- - (void)imageView:(UIImageView *)imageView doubleTapDetected:(UITouch *)touch {
- [self handleDoubleTap:[touch locationInView:imageView]];
- }
- - (void)view:(UIView *)view singleTapDetected:(UITouch *)touch{
- [self disMissTap:nil];
- }
- - (void)view:(UIView *)view doubleTapDetected:(UITouch *)touch {
- // Translate touch location to image view location
- CGFloat touchX = [touch locationInView:view].x;
- CGFloat touchY = [touch locationInView:view].y;
- touchX *= 1/self.zoomScale;
- touchY *= 1/self.zoomScale;
- touchX += self.contentOffset.x;
- touchY += self.contentOffset.y;
- [self handleDoubleTap:CGPointMake(touchX, touchY)];
- }
- @end
|