Files
peko-ios/YuMi/Tools/SDPhotoBrowser/SDPhotoBrowser.m
2023-10-09 10:27:53 +08:00

406 lines
14 KiB
Objective-C
Executable File

//
// SDPhotoBrowser.m
// photobrowser
//
// Created by aier on 15-2-3.
// Copyright (c) 2015年 aier. All rights reserved.
//
#import "SDPhotoBrowser.h"
#import "UIImageView+WebCache.h"
#import "SDBrowserImageView.h"
#define iPhoneX ([UIScreen instancesRespondToSelector:@selector(currentMode)] ? CGSizeEqualToSize(CGSizeMake(1125, 2436), [[UIScreen mainScreen] currentMode].size) : NO) //判断是否iPhoneX
#define iPhoneX_NavSafeArea ([[UIScreen mainScreen] bounds].size.height >= 812.0 ? 24 : 0) // 如果是iphoneX 顶部安全区域 24
// ============在这里方便配置样式相关设置===========
// ||
// ||
// ||
// \\//
// \/
#import "SDPhotoBrowserConfig.h"
// =============================================
@implementation SDPhotoBrowser
{
UIScrollView *_scrollView;
BOOL _hasShowedFistView;
UILabel *_indexLabel;
UIButton *_saveButton;
UIActivityIndicatorView *_indicatorView;
BOOL _willDisappear;
UIWindow *currentWindows;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = SDPhotoBrowserBackgrounColor;
_isMe = NO;
}
return self;
}
- (void)didMoveToSuperview
{
[self setupScrollView];
[self setupToolbars];
}
- (void)dealloc
{
[currentWindows removeObserver:self forKeyPath:@"frame"];
self.delegate = nil;
}
- (void)setupToolbars
{
// 1. 序标
UILabel *indexLabel = [[UILabel alloc] init];
indexLabel.bounds = CGRectMake(0, 0, 80, 30);
indexLabel.textAlignment = NSTextAlignmentCenter;
indexLabel.textColor = [UIColor whiteColor];
indexLabel.font = [UIFont boldSystemFontOfSize:20];
indexLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5];
indexLabel.layer.cornerRadius = indexLabel.bounds.size.height * 0.5;
indexLabel.clipsToBounds = YES;
if (self.imageCount >= 1) {
indexLabel.text = [NSString stringWithFormat:@"1/%ld", (long)self.imageCount];
}
_indexLabel = indexLabel;
[self addSubview:indexLabel];
// 2.保存按钮
UIButton *saveButton = [[UIButton alloc] init];
[saveButton setTitle:YMLocalizedString(@"SDPhotoBrowser0") forState:UIControlStateNormal];
[saveButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
saveButton.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.90f];
saveButton.layer.cornerRadius = 5;
saveButton.clipsToBounds = YES;
[saveButton addTarget:self action:@selector(saveImage) forControlEvents:UIControlEventTouchUpInside];
_saveButton = saveButton;
[self addSubview:saveButton];
}
- (void)saveImage
{
int index = _scrollView.contentOffset.x / _scrollView.bounds.size.width;
UIImageView *currentImageView = _scrollView.subviews[index];
UIImageWriteToSavedPhotosAlbum(currentImageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
if (_indicatorView == nil) {
_indicatorView = [[UIActivityIndicatorView alloc] init];
_indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
_indicatorView.center = self.center;
[[UIApplication sharedApplication].keyWindow addSubview:_indicatorView];
}
[_indicatorView startAnimating];
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
{
[_indicatorView stopAnimating];
UILabel *label = [[UILabel alloc] init];
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor colorWithRed:0.1f green:0.1f blue:0.1f alpha:0.90f];
label.layer.cornerRadius = 5;
label.clipsToBounds = YES;
label.bounds = CGRectMake(0, 0, 150, 30);
label.center = self.center;
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont boldSystemFontOfSize:17];
[[UIApplication sharedApplication].keyWindow addSubview:label];
[[UIApplication sharedApplication].keyWindow bringSubviewToFront:label];
if (error) {
label.text = SDPhotoBrowserSaveImageFailText;
} else {
label.text = SDPhotoBrowserSaveImageSuccessText;
}
[label performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1.0];
}
- (void)setupScrollView
{
_scrollView = [[UIScrollView alloc] init];
_scrollView.delegate = self;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.pagingEnabled = YES;
[self addSubview:_scrollView];
for (int i = 0; i < self.imageCount; i++) {
SDBrowserImageView *imageView = [[SDBrowserImageView alloc] init];
imageView.tag = i;
// 单击图片
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(photoClick:)];
// 双击放大图片
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageViewDoubleTaped:)];
doubleTap.numberOfTapsRequired = 2;
[singleTap requireGestureRecognizerToFail:doubleTap];
[imageView addGestureRecognizer:singleTap];
[imageView addGestureRecognizer:doubleTap];
[_scrollView addSubview:imageView];
}
[self setupImageOfImageViewForIndex:self.currentImageIndex];
}
// 加载图片
- (void)setupImageOfImageViewForIndex:(NSInteger)index
{
SDBrowserImageView *imageView = _scrollView.subviews[index];
self.currentImageIndex = index;
if (imageView.hasLoadedImage) return;
if ([self highQualityImageURLForIndex:index]) {
[imageView setImageWithURL:[self highQualityImageURLForIndex:index] placeholderImage:[self placeholderImageForIndex:index]];
} else {
if([self highQualityImageForIndex: index]){
imageView.image = [self highQualityImageForIndex: index];
}else{
imageView.image = [self placeholderImageForIndex:index];
}
}
imageView.hasLoadedImage = YES;
}
- (void)photoClick:(UITapGestureRecognizer *)recognizer
{
_scrollView.hidden = YES;
_willDisappear = YES;
SDBrowserImageView *currentImageView = (SDBrowserImageView *)recognizer.view;
NSInteger currentIndex = currentImageView.tag;
if (self.isHaveUserAdd) {
currentIndex = currentImageView.tag + 1;
}
UIView *sourceView = nil;
if ([self.sourceImagesContainerView isKindOfClass:UICollectionView.class]) {
UICollectionView *view = (UICollectionView *)self.sourceImagesContainerView;
NSIndexPath *path = [NSIndexPath indexPathForItem:currentIndex inSection:0];
sourceView = [view cellForItemAtIndexPath:path];
}else {
if (self.currentImageIndex<self.sourceImagesContainerView.subviews.count) {
sourceView = self.sourceImagesContainerView.subviews[self.currentImageIndex];
}
}
CGRect targetTemp = (!CGRectEqualToRect(self.sourceImagesFrame, CGRectZero)) ? self.sourceImagesFrame : [self.sourceImagesContainerView convertRect:sourceView.frame toView:self];
UIImageView *tempView = [[UIImageView alloc] init];
tempView.contentMode = sourceView.contentMode;
tempView.clipsToBounds = YES;
tempView.image = currentImageView.image;
CGFloat h = (self.bounds.size.width / currentImageView.image.size.width) * currentImageView.image.size.height;
if (!currentImageView.image) { // 防止 因imageview的image加载失败 导致 崩溃
h = self.bounds.size.height;
}
tempView.bounds = CGRectMake(0, 0, self.bounds.size.width, h);
tempView.center = self.center;
[self addSubview:tempView];
_saveButton.hidden = YES;
[UIView animateWithDuration:SDPhotoBrowserHideImageAnimationDuration animations:^{
tempView.frame = targetTemp;
self.backgroundColor = [UIColor clearColor];
_indexLabel.alpha = 0.1;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
- (void)imageViewDoubleTaped:(UITapGestureRecognizer *)recognizer
{
SDBrowserImageView *imageView = (SDBrowserImageView *)recognizer.view;
CGFloat scale;
if (imageView.isScaled) {
scale = 1.0;
} else {
scale = 2.0;
}
SDBrowserImageView *view = (SDBrowserImageView *)recognizer.view;
[view doubleTapToZommWithScale:scale];
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect rect = self.bounds;
rect.size.width += SDPhotoBrowserImageViewMargin * 2;
_scrollView.bounds = rect;
_scrollView.center = self.center;
CGFloat y = 0;
CGFloat w = _scrollView.frame.size.width - SDPhotoBrowserImageViewMargin * 2;
CGFloat h = _scrollView.frame.size.height;
[_scrollView.subviews enumerateObjectsUsingBlock:^(SDBrowserImageView *obj, NSUInteger idx, BOOL *stop) {
CGFloat x = SDPhotoBrowserImageViewMargin + idx * (SDPhotoBrowserImageViewMargin * 2 + w);
obj.frame = CGRectMake(x, y, w, h);
}];
_scrollView.contentSize = CGSizeMake(_scrollView.subviews.count * _scrollView.frame.size.width, 0);
_scrollView.contentOffset = CGPointMake(self.currentImageIndex * _scrollView.frame.size.width, 0);
if (!_hasShowedFistView) {
[self showFirstImage];
}
_indexLabel.center = CGPointMake(self.bounds.size.width * 0.5, 35+iPhoneX_NavSafeArea);
_saveButton.frame = CGRectMake(30, self.bounds.size.height - 70, 50, 25);
}
- (void)show
{
currentWindows = [UIApplication sharedApplication].keyWindow;
self.frame = currentWindows.bounds;
[currentWindows addObserver:self forKeyPath:@"frame" options:0 context:nil];
[currentWindows addSubview:self];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(UIView *)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"frame"]) {
self.frame = object.bounds;
SDBrowserImageView *currentImageView = _scrollView.subviews[_currentImageIndex];
if ([currentImageView isKindOfClass:[SDBrowserImageView class]]) {
[currentImageView clear];
}
}
}
- (void)showFirstImage
{
UIView *sourceView = nil;
if ([self.sourceImagesContainerView isKindOfClass:UICollectionView.class]) {
UICollectionView *view = (UICollectionView *)self.sourceImagesContainerView;
if (self.isHaveUserAdd) {
NSInteger haveUserIndex = self.currentImageIndex + 1;
NSIndexPath *path = [NSIndexPath indexPathForItem:haveUserIndex inSection:0];
sourceView = [view cellForItemAtIndexPath:path];
} else {
NSIndexPath *path = [NSIndexPath indexPathForItem:self.currentImageIndex inSection:0];
sourceView = [view cellForItemAtIndexPath:path];
}
}else {
if (self.currentImageIndex<self.sourceImagesContainerView.subviews.count) {
sourceView = self.sourceImagesContainerView.subviews[self.currentImageIndex];
}
}
CGRect rect = (!CGRectEqualToRect(self.sourceImagesFrame, CGRectZero)) ? self.sourceImagesFrame : [self.sourceImagesContainerView convertRect:sourceView.frame toView:self];
UIImageView *tempView = [[UIImageView alloc] init];
tempView.image = [self placeholderImageForIndex:self.currentImageIndex];
[self addSubview:tempView];
CGRect targetTemp = [_scrollView.subviews[self.currentImageIndex] bounds];
tempView.frame = rect;
tempView.contentMode = [_scrollView.subviews[self.currentImageIndex] contentMode];
_scrollView.hidden = YES;
[UIView animateWithDuration:SDPhotoBrowserShowImageAnimationDuration animations:^{
tempView.center = self.center;
tempView.bounds = (CGRect){CGPointZero, targetTemp.size};
} completion:^(BOOL finished) {
_hasShowedFistView = YES;
[tempView removeFromSuperview];
_scrollView.hidden = NO;
}];
}
- (UIImage *)placeholderImageForIndex:(NSInteger)index
{
if ([self.delegate respondsToSelector:@selector(photoBrowser:placeholderImageForIndex:)]) {
return [self.delegate photoBrowser:self placeholderImageForIndex:index];
}
return nil;
}
-(UIImage *)highQualityImageForIndex:(NSInteger)index{
if ([self.delegate respondsToSelector:@selector(photoBrowser:highQualityImageForIndex:)]) {
return [self.delegate photoBrowser:self highQualityImageForIndex:index];
}
return nil;
}
- (NSURL *)highQualityImageURLForIndex:(NSInteger)index
{
if ([self.delegate respondsToSelector:@selector(photoBrowser:highQualityImageURLForIndex:)]) {
return [self.delegate photoBrowser:self highQualityImageURLForIndex:index];
}
return nil;
}
#pragma mark - scrollview代理方法
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
int index = (scrollView.contentOffset.x + _scrollView.bounds.size.width * 0.5) / _scrollView.bounds.size.width;
// 有过缩放的图片在拖动一定距离后清除缩放
CGFloat margin = 150;
CGFloat x = scrollView.contentOffset.x;
if ((x - index * self.bounds.size.width) > margin || (x - index * self.bounds.size.width) < - margin) {
if(index < _scrollView.subviews.count){
SDBrowserImageView *imageView = _scrollView.subviews[index];
if (imageView.isScaled) {
[UIView animateWithDuration:0.5 animations:^{
imageView.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[imageView eliminateScale];
}];
}
}
}
if (!_willDisappear) {
if (self.isMe) {
if (self.isHaveUserAdd) {
_indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index + 1, (long)self.imageCount];
} else {
_indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index, (long)self.imageCount];
}
}else{
_indexLabel.text = [NSString stringWithFormat:@"%d/%ld", index + 1, (long)self.imageCount];
}
}
[self setupImageOfImageViewForIndex:index];
}
@end