iOS大图预览和上下拖动退出的逻辑

一般的app大图预览都是使用collectionview布局的,每一个cell对应一张图片
cell里的逻辑如下:

//
// Created by bcy on 2017/9/6.
// Copyright (c) 2017 mirroon. All rights reserved.
//

#import "BCYFoundation.h"

#import <BCYUIKit/BCYUIKit.h>

#import "BCYFullScreenImageCollectionViewCell.h"
#import "BCYFullScreenImageModel.h"
#import "BCYFullScreenImageViewerConfiguration.h"
#import "YYCGUtilities.h"
#import <SDWebImage/UIImage+GIF.h>

#import "StringUtils.h"
#import "UIView+YYAdd.h"
#import "YYAnimatedImageView.h"

@interface BCYFullScreenImageCollectionViewCell () <UIScrollViewDelegate>
@property (nonatomic, strong) YYAnimatedImageView *imageView;
@property (nonatomic, strong) UIScrollView *contentScrollView;
@property (nonatomic, strong) UILabel *waterMarkLabel;
@end

@implementation BCYFullScreenImageCollectionViewCell {
}

#pragma mark -Override Methods

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        _contentScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, kScreenWidth, kScreenHeight)];
        _contentScrollView.showsVerticalScrollIndicator = NO;
        _contentScrollView.showsHorizontalScrollIndicator = NO;
        _contentScrollView.backgroundColor = UIColor.from(CAssetBlack);
        _contentScrollView.zoomScale = 1.0;
        _contentScrollView.minimumZoomScale = 1.0;
        _contentScrollView.maximumZoomScale = 2.0f;
        _contentScrollView.delegate = self;
        [self.contentView addSubview:_contentScrollView];

        _imageView = [[YYAnimatedImageView alloc]
            initWithFrame:CGRectMake(0.0f, kScreenHeight / 2.0f - kScreenWidth / 2.0f, kScreenWidth, kScreenWidth)];
        _imageView.image = UIImage.from(IAssetPlaceholder);
        [self.contentScrollView addSubview:_imageView];

        _waterMarkLabel = [[UILabel alloc] init];
        _waterMarkLabel.frame = CGRectMake(0.0f, _imageView.height - 26.0f - 6.0f, _imageView.width - 6.0f, 26.0f);
        _waterMarkLabel.textColor = UIColor.from(CAssetMidGray);
        _waterMarkLabel.font = [UIFont systemFontOfSize:9.0f];
        _waterMarkLabel.numberOfLines = 2;
        _waterMarkLabel.textAlignment = NSTextAlignmentRight;
        [_imageView addSubview:_waterMarkLabel];

        UITapGestureRecognizer *singleTapRecognizer =
            [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_contentScrollViewSingleTapped:)];
        [_contentScrollView addGestureRecognizer:singleTapRecognizer];

        UITapGestureRecognizer *doubleTapRecognizer =
            [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_contentScrollViewDoubleTapped:)];
        doubleTapRecognizer.numberOfTapsRequired = 2;
        [_contentScrollView addGestureRecognizer:doubleTapRecognizer];

        [singleTapRecognizer requireGestureRecognizerToFail:doubleTapRecognizer];
        //添加上下拉退出
        UISwipeGestureRecognizer *swipeUpRecognizer =
            [[UISwipeGestureRecognizer alloc] initWithTarget:self
                                                      action:@selector(_contentScrollViewSwipeBackRecognizer:)];
        UISwipeGestureRecognizer *swipeDownRecognizer =
            [[UISwipeGestureRecognizer alloc] initWithTarget:self
                                                      action:@selector(_contentScrollViewSwipeBackRecognizer:)];

        swipeUpRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
        swipeDownRecognizer.direction = UISwipeGestureRecognizerDirectionDown;

        [self addGestureRecognizer:swipeDownRecognizer];
        [self addGestureRecognizer:swipeUpRecognizer];
    }

    return self;
}

#pragma mark -Public Methods

- (void)updateContentWithImageModel:(BCYFullScreenImageModel *)imageModel
                          indexPath:(NSIndexPath *)indexPath
                      configuration:(BCYFullScreenImageViewerConfiguration *)configuration {
    _indexPath = indexPath;
    _imageModel = imageModel;
    _configuration = configuration;

    if (imageModel.rotated) {
        _contentScrollView.transform = CGAffineTransformIdentity;
        _contentScrollView.frame = CGRectMake(0, 0, kScreenHeight, kScreenWidth);
        _contentScrollView.center = [UIApplication sharedApplication].keyWindow.center;
        _contentScrollView.transform = CGAffineTransformMakeRotation((CGFloat)M_PI_2);
        CGFloat top = 0.0f;
        if (imageModel.rotatedSize.height < kScreenWidth) {
            top = (kScreenWidth - imageModel.rotatedSize.height) / 2.0f;
        }
        _imageView.frame = CGRectMake(0, top, kScreenHeight, imageModel.rotatedSize.height);
        _contentScrollView.contentSize = CGSizeMake(kScreenHeight, roundf(imageModel.rotatedSize.height));
    } else {
        _contentScrollView.transform = CGAffineTransformIdentity;
        _contentScrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
        _contentScrollView.center = [UIApplication sharedApplication].keyWindow.center;
        CGFloat top = 0.0f;
        if (imageModel.normalSize.height < kScreenHeight) {
            top = (kScreenHeight - imageModel.normalSize.height) / 2.0f;
        }
        _imageView.frame = CGRectMake(0, top, kScreenWidth, imageModel.normalSize.height);
        _contentScrollView.contentSize = CGSizeMake(kScreenWidth, imageModel.normalSize.height);
    }
    /**优先使用data属性来渲染图片*/
    if (imageModel.data) {
        _imageView.image = [UIImage sd_animatedGIFWithData:imageModel.data];
    } else {
        _imageView.image = imageModel.image;
    }

    _waterMarkLabel.frame = CGRectMake(0.0f, _imageView.height - 26.0f - 6.0f, _imageView.width - 6.0f, 26.0f);
    if (((_configuration.options & BCYFullScreenImageViewerOptionUseNativeWaterMark) > 0)) {
        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        paragraphStyle.lineSpacing = 4.0f;
        paragraphStyle.alignment = NSTextAlignmentRight;
        _waterMarkLabel.attributedText = [[NSAttributedString alloc]
            initWithString:[NSString stringWithFormat:@"©%@\n半次元-二次元创作者社区",
                                                      [StringUtils safeString:_configuration.userName
                                                                defaultString:nil]]
                attributes:@{NSParagraphStyleAttributeName : paragraphStyle}];

        _waterMarkLabel.hidden = NO;
        if ([imageModel hasOriginalImageLocalCache]) {
            /**查看原图的情况下,如果用户未设置禁止右键,则隐藏前端水印*/
            _waterMarkLabel.hidden = YES;
        }
    } else {
        _waterMarkLabel.hidden = YES;
    }
}

- (void)rotateImage {
    if (!_imageModel.rotated) {
        _imageModel.rotated = YES;
        _contentScrollView.frame = CGRectMake(0, 0, kScreenHeight, kScreenWidth);
        _contentScrollView.center = [UIApplication sharedApplication].keyWindow.center;
        CGFloat top = 0.0f;
        if (_imageModel.rotatedSize.height < kScreenWidth) {
            top = (kScreenWidth - _imageModel.rotatedSize.height) / 2.0f;
        }
        _imageView.frame = CGRectMake(0, top, kScreenHeight, _imageModel.rotatedSize.height);
        _waterMarkLabel.frame = CGRectMake(0.0f, _imageView.height - 26.0f - 6.0f, _imageView.width - 6.0f, 26.0f);
        _contentScrollView.contentSize = CGSizeMake(kScreenHeight, roundf(_imageModel.rotatedSize.height));
        [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
        [UIView animateWithDuration:0.3f
            animations:^{
                self.contentScrollView.transform = CGAffineTransformIdentity;
                self.contentScrollView.transform = CGAffineTransformMakeRotation((CGFloat)M_PI_2);
            }
            completion:^(BOOL finished) {
                if (finished) {
                    [[UIApplication sharedApplication] endIgnoringInteractionEvents];
                }
            }];
    } else {
        _imageModel.rotated = NO;
        CGFloat top = 0.0f;
        if (_imageModel.normalSize.height < kScreenHeight) {
            top = (kScreenHeight - _imageModel.normalSize.height) / 2.0f;
        }
        _imageModel.rotated = NO;
        _imageView.frame = CGRectMake(0, top, kScreenWidth, _imageModel.normalSize.height);
        _waterMarkLabel.frame = CGRectMake(0.0f, _imageView.height - 26.0f - 6.0f, _imageView.width - 6.0f, 26.0f);
        _contentScrollView.contentSize = CGSizeMake(kScreenWidth, _imageModel.normalSize.height);
        [[UIApplication sharedApplication] beginIgnoringInteractionEvents];
        [UIView animateWithDuration:0.3f
            animations:^{
                self.contentScrollView.transform = CGAffineTransformIdentity;
                self.contentScrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
                self.contentScrollView.center = [UIApplication sharedApplication].keyWindow.center;
            }
            completion:^(BOOL finished) {
                if (finished) {
                    [[UIApplication sharedApplication] endIgnoringInteractionEvents];
                }
            }];
    }
}

#pragma mark -UIScrollView Delegate Methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return _imageView;
}
- (void)scrollViewDidZoom:(UIScrollView *)scrollView {
    CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width)
                          ? (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5f
                          : 0.f;
    CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height)
                          ? (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5f
                          : 0.f;

    _imageView.center =
        CGPointMake(scrollView.contentSize.width * 0.5f + offsetX, scrollView.contentSize.height * 0.5f + offsetY);
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    //大图手势返回,因为大图会优先处理ScrollView的滑动,在这里判断是否滑动越界,如果是就触发对应的返回动画
    //在图片未被放大和旋转时触发
    if (scrollView.zoomScale <= 1.0f && !_imageModel.rotated) {
        CGFloat offset = scrollView.contentOffset.y;
        if (offset < -20) {
            [self moveScrollView:BCYScrollViewDirectionDown];
        } else if (offset + kScreenHeight > scrollView.contentSize.height + 20) {
            //长图上拉
            [self moveScrollView:BCYScrollViewDirectionUp];
        }
    }

    if (_imageModel.rotated) {
        if (_contentScrollView.contentOffset.y < -20) {
            /**注意防越界!!!*/
            if (_delegate && [_delegate respondsToSelector:@selector(getTotalItemCount)]) {
                if (_indexPath.item + 1 < [_delegate getTotalItemCount]) {
                    if ([_delegate respondsToSelector:@selector(scrollToIndex:)]) {
                        [_delegate scrollToIndex:_indexPath.item + 1];
                    }
                }
            }
        } else if (_contentScrollView.contentOffset.y + kScreenWidth > _contentScrollView.contentSize.height + 20) {
            if (_indexPath.item - 1 >= 0) {
                if ([_delegate respondsToSelector:@selector(scrollToIndex:)]) {
                    [_delegate scrollToIndex:_indexPath.item - 1];
                }
            }
        }
    }
}

#pragma mark -Action Methods
//单击屏幕触发隐藏工具栏事件
- (void)_contentScrollViewSingleTapped:(id)sender {
    if ([self.delegate respondsToSelector:@selector(hideToolBar)]) {
        [self.delegate hideToolBar];
    }
}

- (void)_contentScrollViewDoubleTapped:(id)sender {
    if (_contentScrollView.zoomScale > 1.f) {
        [_contentScrollView setZoomScale:1.f animated:YES];
    } else {
        [_contentScrollView setZoomScale:2.f animated:YES];
    }
}

- (void)_contentScrollViewSwipeBackRecognizer:(UISwipeGestureRecognizer *)sender {
    //小图上下拉手势响应
    if (sender.direction == UISwipeGestureRecognizerDirectionDown) {
        [self moveScrollView:BCYScrollViewDirectionDown];
    } else {
        [self moveScrollView:BCYScrollViewDirectionUp];
    }
}

- (void)moveScrollView:(BCYScrollViewDirection)direction {
    //预览器移动滑出动画
    if ([self.delegate respondsToSelector:@selector(setBackgroundTranslucent)] &&
        [self.delegate respondsToSelector:@selector(hideToolBar)]) {
        [self.delegate setBackgroundTranslucent];
        [self.delegate hideToolBar];
    }
    //旋转复位
    if (self.imageModel.rotated) {
        self.contentScrollView.transform = CGAffineTransformIdentity;
        self.contentScrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight);
        self.contentScrollView.center = [UIApplication sharedApplication].keyWindow.center;
    }
    //根据滑动方向执行对应方向的动画
    [UIView animateWithDuration:BCY_DEFAULT_ANIMATION_DURATION
        animations:^(void) {
            self.contentScrollView.transform =
                CGAffineTransformTranslate(self.contentScrollView.transform, 0,
                                           direction == BCYScrollViewDirectionDown ? kScreenHeight : -kScreenHeight);
        }
        completion:^(BOOL isFinish) {
            if ([self.delegate respondsToSelector:@selector(dismiss)]) {
                [self.delegate dismiss];
            }
        }];
}

@end

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容