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