美文网首页
iOS大图预览和上下拖动退出的逻辑

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

作者: 咸鱼有只喵 | 来源:发表于2018-11-06 17:11 被阅读46次

    一般的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
    
    

    相关文章

      网友评论

          本文标题:iOS大图预览和上下拖动退出的逻辑

          本文链接:https://www.haomeiwen.com/subject/cjwuxqtx.html