Files
yuyin_ios/SweetParty/第三方库/KNPhotoBrowser/KNPhotoBrowser.m
2025-08-08 11:05:33 +08:00

1482 lines
59 KiB
Objective-C
Executable File

//
// KNPhotoBrowser.h
// KNPhotoBrowser
//
// Created by LuKane on 16/8/18.
// Copyright © 2016年 LuKane. All rights reserved.
//
/**
* 如果 bug ,希望各位在 github 上通过'邮箱' 或者直接 issue 指出, 谢谢
* github地址 : https://github.com/LuKane/KNPhotoBrowser
* 项目会越来越丰富,也希望大家一起来增加功能 , 欢迎 Star
*/
#import "KNPhotoBrowser.h"
#import "KNPhotoImageCell.h"
#import "KNPhotoVideoCell.h"
#import "KNPhotoBrowserPch.h"
#import "KNPhotoDownloadMgr.h"
#import "KNPhotoBrowserNumView.h"
#import <SDWebImage/UIImageView+WebCache.h>
#import <SDWebImage/SDWebImagePrefetcher.h>
#import <SDWebImage/SDImageCache.h>
#import <MobileCoreServices/UTCoreTypes.h>
#import <Photos/Photos.h>
#import <objc/runtime.h>
@interface KNPhotoBrowser ()<UICollectionViewDelegate,UICollectionViewDataSource,KNPhotoVideoCellDelegate>{
UICollectionViewFlowLayout *_layout;
KNPhotoBrowserNumView *_numView;
UIPageControl *_pageControl;
UIButton *_operationBtn;
KNPhotoBrowserImageView *_imageView;
KNProgressHUD *_progressHUD;
NSArray *_customArr; // custom view on photoBrowser
CGFloat _offsetPageIndex; // record location index, for screen rotate
NSInteger _page; // current page
BOOL _isShowed; // is showed?
BOOL _statusBarHidden;// record original status bar is hidden or not
BOOL _isDismissed; // when photoBrowser will dismiss , it will be true, default is false
}
@property (nonatomic, strong) NSArray *tempArr;
@property (nonatomic, strong) NSMutableArray *followArr;
@property (nonatomic, weak ) UICollectionView *collectionView;
@property (nonatomic, assign) CGPoint startLocation;
@property (nonatomic, assign) CGRect startFrame;
@property (nonatomic, strong) KNPhotoDownloadMgr *downloadMgr;
@end
@implementation KNPhotoBrowser
- (NSMutableArray *)followArr{
if (!_followArr) {
_followArr = [NSMutableArray array];
}
return _followArr;
}
- (KNPhotoDownloadMgr *)downloadMgr{
if (!_downloadMgr) {
_downloadMgr = [[KNPhotoDownloadMgr shareInstance] init];
}
return _downloadMgr;
}
- (instancetype)init{
if (self = [super init]) {
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
self.modalPresentationStyle = UIModalPresentationCustom;
_statusBarHidden = [UIApplication sharedApplication].statusBarHidden;
self.animatedMode = UIViewContentModeScaleToFill;
self.presentedMode = UIViewContentModeScaleAspectFit;
self.isSoloAmbient = true;
}
return self;
}
- (BOOL)shouldAutorotate{
return true;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
- (BOOL)prefersStatusBarHidden{
return _statusBarHidden;
}
- (void)hiddenStatusBar{
if (@available(iOS 13.0, *)) {
} else {
UIView *statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];
[UIView animateWithDuration:0.15 animations:^{
statusBar.transform = CGAffineTransformMakeTranslation(0, - statusBar.bounds.size.height);
}];
}
}
- (void)showStatusBar{
if (@available(iOS 13.0, *)) {
} else {
UIView *statusBar = [[UIApplication sharedApplication] valueForKey:@"statusBar"];
[UIView animateWithDuration:0.15 animations:^{
statusBar.transform = CGAffineTransformIdentity;
}];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = false;
self.view.backgroundColor = [UIColor blackColor];
[self prefetchImage];
[self initCollectionView];
[self initNumView];
[self initPageControl];
[self initOperationView];
[self initCustomView];
if (@available(iOS 11.0, *)){
_collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
}
if(self.isNeedPanGesture){
[self.view addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panDidGesture:)]];
}
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceWillOrientation)
name:UIApplicationWillChangeStatusBarOrientationNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(deviceDidOrientation)
name:UIApplicationDidChangeStatusBarOrientationNotification
object:nil];
}
/* prefetch 8 images with SDWebImagePrefetcher */
- (void)prefetchImage{
if(self.isNeedPrefetch == false) return;
if(_itemsArr.count == 0) return;
NSMutableArray *urlArr = [NSMutableArray array];
if(_itemsArr.count <= PhotoBrowserPrefetchNum + 1){
for (NSInteger i = 0; i < _itemsArr.count; i++) {
if(i != _currentIndex){
KNPhotoItems *items = _itemsArr[i];
if(items.url != nil && [items.url hasPrefix:@"http"] && items.isVideo == false){
[urlArr addObject:[NSURL URLWithString:items.url]];
}
}
}
}else{
NSInteger index = 0;
if(_currentIndex == _itemsArr.count - 1){
index = _itemsArr.count;
}else{
index = _currentIndex + 1;
}
for (NSInteger i = index; i < _itemsArr.count; i++) {
KNPhotoItems *items = _itemsArr[i];
if(items.url != nil && items.isVideo == false && [items.url hasPrefix:@"http"]){
[urlArr addObject:[NSURL URLWithString:items.url]];
}
}
}
if(urlArr.count != 0){
[[SDWebImagePrefetcher sharedImagePrefetcher] prefetchURLs:urlArr];
}
}
/* init collectionView */
- (void)initCollectionView{
// 1.layout
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
// 2.collectionView
UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero
collectionViewLayout:layout];
[collectionView setDataSource:self];
[collectionView setDelegate:self];
[collectionView setPagingEnabled:true];
[collectionView setBackgroundColor:[UIColor clearColor]];
[collectionView setScrollsToTop:false];
[collectionView setShowsHorizontalScrollIndicator:false];
[collectionView setContentOffset:CGPointZero];
[collectionView setAlpha:0.f];
[collectionView setBounces:true];
[self.view addSubview:collectionView];
_layout = layout;
_collectionView = collectionView;
[_collectionView registerClass:[KNPhotoImageCell class] forCellWithReuseIdentifier:@"KNPhotoImageCellID"];
[_collectionView registerClass:[KNPhotoVideoCell class] forCellWithReuseIdentifier:@"KNPhotoVideoCellID"];
KNPhotoBrowserImageView *imageView = [[KNPhotoBrowserImageView alloc] initWithFrame:self.view.bounds];
[imageView setHidden:true];
[self.view addSubview:imageView];
KNProgressHUD *progressHUD = [[KNProgressHUD alloc] initWithFrame:(CGRect){{([UIScreen mainScreen].bounds.size.width - 40) * 0.5,([UIScreen mainScreen].bounds.size.height - 40) * 0.5},{40,40}}];
[progressHUD setHidden:true];
[self.view addSubview:progressHUD];
_imageView = imageView;
_progressHUD = progressHUD;
}
/* init numView */
- (void)initNumView{
KNPhotoBrowserNumView *numView = [[KNPhotoBrowserNumView alloc] init];
[numView setCurrentNum:(_currentIndex + 1) totalNum:_itemsArr.count];
_page = [numView currentNum];
[numView setHidden:!_isNeedPageNumView];
// whatever is or not set 'isNeedPageNumView' , if itemArr.cout == 1, it must be hidden
if(_itemsArr.count == 1){
[numView setHidden:true];
}
[self.view addSubview:numView];
_numView = numView;
}
/* init PageControl */
- (void)initPageControl{
UIPageControl *pageControl = [[UIPageControl alloc] init];
[pageControl setCurrentPage:_currentIndex];
[pageControl setNumberOfPages:_itemsArr.count];
[pageControl setHidden:!_isNeedPageControl];
// whatever is or not set '_isNeedPageControl' , if itemArr.cout == 1, it must be hidden
if(_itemsArr.count == 1){
[pageControl setHidden:true];
}else {
// if contain video , hide pagecontrol
if ([self isContainVideo:_itemsArr]) {
[pageControl setHidden:true];
}
}
[self.view addSubview:pageControl];
_pageControl = pageControl;
}
/* init customView */
- (void)initCustomView{
if ([self isEmptyArray:_customArr]) return;
for (UIView *view in _customArr) {
[self.view addSubview:view];
}
}
- (BOOL)isContainVideo:(NSArray <KNPhotoItems *> *)itemsArr {
for (KNPhotoItems *items in itemsArr) {
if (items.isVideo) {
return true;
}
}
return false;
}
/* init right top Btn */
- (void)initOperationView{
NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(@"KNPhotoBrowser")];
UIButton *operationBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[operationBtn.layer setCornerRadius:3];
[operationBtn setClipsToBounds:true];
[operationBtn setBackgroundColor:[UIColor blackColor]];
[operationBtn setAlpha:0.4];
if(UIScreen.mainScreen.scale < 3) {
[operationBtn setBackgroundImage:[UIImage imageNamed:@"KNPhotoBrowser.bundle/more_tap@2x.png" inBundle:bundle compatibleWithTraitCollection:nil] forState:UIControlStateNormal];
}else {
[operationBtn setBackgroundImage:[UIImage imageNamed:@"KNPhotoBrowser.bundle/more_tap@3x.png" inBundle:bundle compatibleWithTraitCollection:nil] forState:UIControlStateNormal];
}
[operationBtn addTarget:self action:@selector(operationBtnIBAction) forControlEvents:UIControlEventTouchUpInside];
[operationBtn setHidden:!_isNeedRightTopBtn];
_operationBtn = operationBtn;
[self.view addSubview:operationBtn];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return self.itemsArr.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
KNPhotoItems *item = self.itemsArr[indexPath.row];
if (item.isVideo) {
KNPhotoVideoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"KNPhotoVideoCellID" forIndexPath:indexPath];
[cell setDelegate:self];
return cell;
}else {
KNPhotoImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"KNPhotoImageCellID" forIndexPath:indexPath];
__weak typeof(self) weakSelf = self;
cell.singleTap = ^{
[weakSelf dismiss];
};
cell.longPressTap = ^{
[weakSelf longPressIBAction];
};
return cell;
}
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
[cell prepareForReuse];
KNPhotoItems *item = self.itemsArr[indexPath.row];
UIImageView *tempView = [self tempViewFromSourceViewWithCurrentIndex:indexPath.row];
if (item.isVideo) {
if (_isDismissed == true) {
return;
}
KNPhotoVideoCell *videoCell = (KNPhotoVideoCell *)cell;
videoCell.isSoloAmbient = _isSoloAmbient;
if (_isNeedOnlinePlay) {
[videoCell playerOnLinePhotoItems:item placeHolder:tempView.image];
}else {
[videoCell playerLocatePhotoItems:item placeHolder:tempView.image];
}
if (_isNeedAutoPlay == true) {
[videoCell setIsNeedAutoPlay:true];
}
[videoCell setPresentedMode:self.presentedMode];
} else {
KNPhotoImageCell *imageCell = (KNPhotoImageCell *)cell;
[imageCell imageWithUrl:item.url placeHolder:tempView.image photoItem:item];
[imageCell setPresentedMode:self.presentedMode];
}
}
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
if (self.itemsArr.count <= indexPath.row) {
return;
}
KNPhotoItems *item = self.itemsArr[indexPath.row];
if (item.isVideo && [cell isKindOfClass:[KNPhotoVideoCell class]]) {
KNPhotoVideoCell *videoCell = (KNPhotoVideoCell *)cell;
[videoCell playerWillEndDisplay];
}
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return collectionView.frame.size;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
CGFloat scrollViewW = scrollView.frame.size.width;
_currentIndex = scrollView.contentOffset.x / _layout.itemSize.width;
CGFloat x = scrollView.contentOffset.x;
NSInteger page = (x + scrollViewW / 2) / scrollViewW;
if(_page != page){
_page = page;
if ([_delegate respondsToSelector:@selector(photoBrowser:scrollToLocateWithIndex:)]) {
[_delegate photoBrowser:self scrollToLocateWithIndex:page];
}
if(_page + 1 <= _itemsArr.count){
[_numView setCurrentNum:_page + 1];
[_pageControl setCurrentPage:_page];
}
}
}
/**
* video will dismiss with animate
*/
- (void)photoVideoAVPlayerDismiss{
[self dismiss];
}
/**
video will long press
*/
- (void)photoVideoAVPlayerLongPress:(UILongPressGestureRecognizer *)longPress{
if (!_isNeedLongPress) return;
if ([_delegate respondsToSelector:@selector(photoBrowser:videoLongPress:index:)]) {
[_delegate photoBrowser:self videoLongPress:longPress index:_currentIndex];
}
}
/**
* pan to dismiss or cancel
*/
- (void)panDidGesture:(UIPanGestureRecognizer *)pan{
if(!isPortrait) return;
KNPhotoItems *items = self.itemsArr[_currentIndex];
CGPoint point = CGPointZero;
CGPoint location = CGPointZero;
CGPoint velocity = CGPointZero;
KNPhotoBrowserImageView *imageView;
id playerView;
if (items.isVideo) {
KNPhotoVideoCell *cell = (KNPhotoVideoCell *)[_collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:_currentIndex inSection:0]];
if (_isNeedOnlinePlay) {
playerView = (KNPhotoAVPlayerView *)cell.onlinePlayerView;
location = [pan locationInView:[(KNPhotoAVPlayerView *)playerView playerBgView]];
}else {
playerView = (KNPhotoLocateAVPlayerView *)cell.locatePlayerView;
location = [pan locationInView:[(KNPhotoLocateAVPlayerView *)playerView playerBgView]];
}
point = [pan translationInView:self.view];
velocity = [pan velocityInView:self.view];
}else{
KNPhotoImageCell *cell = (KNPhotoImageCell *)[_collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:_currentIndex inSection:0]];
imageView = cell.photoBrowerImageView;
if(imageView.scrollView.zoomScale > 1.f) return;
point = [pan translationInView:self.view];
location = [pan locationInView:imageView.scrollView];
velocity = [pan velocityInView:self.view];
}
switch (pan.state) {
case UIGestureRecognizerStateBegan:{
_startLocation = location;
if(items.isVideo){
if (_isNeedOnlinePlay) {
_startFrame = [(KNPhotoAVPlayerView *)playerView playerBgView].frame;
[(KNPhotoAVPlayerView *)playerView setIsNeedVideoPlaceHolder:![(KNPhotoAVPlayerView *)playerView isBeginPlayed]];
}else {
_startFrame = [(KNPhotoLocateAVPlayerView *)playerView playerBgView].frame;
[(KNPhotoLocateAVPlayerView *)playerView setIsNeedVideoPlaceHolder:![(KNPhotoLocateAVPlayerView *)playerView isBeginPlayed]];
}
[playerView playerWillSwipe];
}else{
_startFrame = imageView.imageView.frame;
}
[self customViewSubViewsWillDismiss];
}
break;
case UIGestureRecognizerStateChanged:{
double percent = 1 - fabs(point.y) / self.view.frame.size.height;
double s = MAX(percent, 0.3);
CGFloat width = self.startFrame.size.width * s;
CGFloat height = self.startFrame.size.height * s;
CGFloat rateX = (self.startLocation.x - self.startFrame.origin.x) / self.startFrame.size.width;
CGFloat x = location.x - width * rateX;
CGFloat rateY = (self.startLocation.y - self.startFrame.origin.y) / self.startFrame.size.height;
CGFloat y = location.y - height * rateY;
if(items.isVideo){
if (_isNeedOnlinePlay) {
[(KNPhotoAVPlayerView *)playerView playerView].frame = CGRectMake(x, y, width, height);
[(KNPhotoAVPlayerView *)playerView playerLayer].frame = CGRectMake(0, 0, width, height);
[(KNPhotoAVPlayerView *)playerView placeHolderImgView].frame = CGRectMake(x, y, width, height);
}else {
[(KNPhotoLocateAVPlayerView *)playerView playerView].frame = CGRectMake(x, y, width, height);
[(KNPhotoLocateAVPlayerView *)playerView playerLayer].frame = CGRectMake(0, 0, width, height);
[(KNPhotoLocateAVPlayerView *)playerView placeHolderImgView].frame = CGRectMake(x, y, width, height);
}
}else{
imageView.imageView.frame = CGRectMake(x, y, width, height);
}
self.view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:percent];
}
break;
case UIGestureRecognizerStateEnded:
case UIGestureRecognizerStateCancelled: {
if (items.isVideo) {
if(fabs(point.y) > 200 || fabs(velocity.y) > 500){
// dismiss
if (_isNeedOnlinePlay) {
_startFrame = [(KNPhotoAVPlayerView *)playerView playerView].frame;
}else {
_startFrame = [(KNPhotoLocateAVPlayerView *)playerView playerView].frame;
}
[playerView playerWillReset]; /// stop avplayer and cancel download task
[self cancelVideoDownload];
[playerView setIsNeedVideoPlaceHolder:true];
[self dismiss];
}else{
// cancel
[self cancelVideoAnimation:playerView];
[self customViewSubViewsWillShow];
[playerView setIsNeedVideoPlaceHolder:true];
[playerView playerWillSwipeCancel];
}
}else {
if(fabs(point.y) > 200 || fabs(velocity.y) > 500){
// dismiss
_startFrame = imageView.imageView.frame;
[self dismiss];
}else{
// cancel
[self cancelAnimation:imageView.imageView];
[self customViewSubViewsWillShow];
}
}
}
break;
default:
break;
}
}
/// cancel animate for get back photoBrowser
/// @param imageView current image
- (void)cancelAnimation:(SDAnimatedImageView *)imageView{
[UIView animateWithDuration:PhotoBrowserAnimateTime animations:^{
imageView.frame = self.startFrame;
} completion:^(BOOL finished) {
self.view.backgroundColor = [UIColor blackColor];
}];
}
- (void)cancelVideoAnimation:(id)playerView{
CGRect frame = CGRectMake(0, 0, self.startFrame.size.width, self.startFrame.size.height);
[UIView animateWithDuration:PhotoBrowserAnimateTime animations:^{
if (self.isNeedOnlinePlay) {
[(KNPhotoAVPlayerView *)playerView playerView].frame = frame;
[(KNPhotoAVPlayerView *)playerView playerLayer].frame = frame;
[(KNPhotoAVPlayerView *)playerView placeHolderImgView].frame = frame;
}else {
[(KNPhotoLocateAVPlayerView *)playerView playerView].frame = frame;
[(KNPhotoLocateAVPlayerView *)playerView playerLayer].frame = frame;
[(KNPhotoLocateAVPlayerView *)playerView placeHolderImgView].frame = frame;
}
} completion:^(BOOL finished) {
self.view.backgroundColor = [UIColor blackColor];
}];
}
#pragma mark - photoBrowser will present -- window
- (void)present{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
[window.rootViewController presentViewController:self animated:false completion:^{
}];
}
#pragma mark - photoBrowser will present -- controller
- (void)present:(UIViewController *)controller {
[controller presentViewController:self animated:false completion:^{
}];
}
#pragma mark - photoBrowser will present -- controller
- (void)presentOn:(UIViewController *)controller {
[controller presentViewController:self animated:false completion:^{
}];
}
/**
photoBrowser first show
*/
- (void)photoBrowserWillShowWithAnimated{
// 0. catch absolute data source
_tempArr = [NSMutableArray arrayWithArray:_itemsArr];
// 1.set collectionView offset by currentIndex
[_collectionView setContentOffset:(CGPoint){_currentIndex * _layout.itemSize.width,0} animated:false];
// 2.set sourceView for get the frame and image
KNPhotoItems *items = _itemsArr[_currentIndex];
UIView *sourceView;
sourceView = items.sourceView;
CGRect rect = [sourceView convertRect:[sourceView bounds] toView:[UIApplication sharedApplication].keyWindow];
UIImageView *tempView = [self tempViewFromSourceViewWithCurrentIndex:_currentIndex];
tempView.contentMode = self.animatedMode;
if (CGRectEqualToRect(rect, CGRectZero)) {
// when source == nil
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self->_collectionView setAlpha:1];
} completion:^(BOOL finished) {
[self->_collectionView setHidden:false];
[self hiddenStatusBar];
[UIView animateWithDuration:0.15 animations:^{
[tempView setAlpha:0.f];
} completion:^(BOOL finished) {
[tempView removeFromSuperview];
}];
self->_page = self.currentIndex;
}];
return;
}
// in case tempView'image create fail
if(tempView.image == nil){
[_collectionView setHidden:false];
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self->_collectionView setAlpha:1];
} completion:^(BOOL finished) {
self->_page = self.currentIndex;
}];
return;
}
[tempView setFrame:rect];
tempView.layer.cornerRadius = 0.001;
tempView.clipsToBounds = true;
[self.view insertSubview:tempView atIndex:0];
CGSize tempRectSize;
CGFloat width = tempView.image.size.width;
CGFloat height = tempView.image.size.height;
if(isPortrait == true){
if (width/height >= PBViewWidth / PBViewHeight) {
tempRectSize = (CGSize){PBViewWidth,(height * PBViewWidth / width) > PBViewHeight?PBViewHeight:(height * PBViewWidth / width)};
}else {
if (items.isVideo == true) {
tempRectSize = (CGSize){width * PBViewHeight / height,PBViewHeight};
}else {
tempRectSize = (CGSize){PBViewWidth,(height * PBViewWidth / width) > PBViewHeight?PBViewHeight:(height * PBViewWidth / width)};
}
}
}else{
if(width > height){
if(width / height > PBViewWidth / PBViewHeight){
tempRectSize = (CGSize){PBViewWidth,height * PBViewWidth / width};
}else{
tempRectSize = (CGSize){PBViewHeight * width / height,PBViewHeight};
}
}else{
tempRectSize = (CGSize){(width * PBViewHeight) / height,PBViewHeight};
}
}
[_collectionView setHidden:true];
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
[tempView setCenter:[self.view center]];
[tempView setBounds:(CGRect){CGPointZero,tempRectSize}];
[self->_collectionView setAlpha:1];
} completion:^(BOOL finished) {
[self->_collectionView setHidden:false];
[self hiddenStatusBar];
[UIView animateWithDuration:0.15 animations:^{
[tempView setAlpha:0.f];
} completion:^(BOOL finished) {
[tempView removeFromSuperview];
}];
self->_page = self.currentIndex;
}];
}
#pragma mark - photoBrowser will dismiss
- (void)dismiss{
// willDismissWithIndex
if([_delegate respondsToSelector:@selector(photoBrowser:willDismissWithIndex:)]){
[_delegate photoBrowser:self willDismissWithIndex:_currentIndex];
}
// if customView on photoBrowser, them must be show
for (UIView *subView in self.followArr) {
[subView setAlpha:1];
}
UIImageView *tempView = [[UIImageView alloc] init];
tempView.clipsToBounds = true;
tempView.layer.cornerRadius = 0.01;
tempView.contentMode = self.animatedMode;
KNPhotoItems *items = _itemsArr[_currentIndex];
if(items.sourceImage){ // locate image by sourceImage of items
tempView.image = items.sourceImage;
[self photoBrowserWillDismissWithAnimated:tempView items:items];
}else{ // net image or locate image without sourceImage of items
if(items.url && items.isVideo == false){
__weak typeof(self) weakself = self;
SDImageCache *cache = [SDImageCache sharedImageCache];
[cache diskImageExistsWithKey:items.url completion:^(BOOL isInCache) {
if(isInCache){
if([[[[items.url lastPathComponent] pathExtension] lowercaseString] isEqualToString:@"gif"]){ // gif image
NSData *data = UIImageJPEGRepresentation([cache imageFromCacheForKey:items.url], 1.f);
if(data){
tempView.image = [weakself imageFromGifFirstImage:data];
}
}else{ // normal image
tempView.image = [cache imageFromCacheForKey:items.url];
}
}else{
tempView.image = [[weakself tempViewFromSourceViewWithCurrentIndex:weakself.currentIndex] image];
}
[self photoBrowserWillDismissWithAnimated:tempView items:items];
}];
}else{
tempView.image = [[self tempViewFromSourceViewWithCurrentIndex:_currentIndex] image];
[self photoBrowserWillDismissWithAnimated:tempView items:items];
}
}
}
- (void)createCustomViewArrOnTopView:(NSArray<UIView *> *)customViewArr
animated:(BOOL)animated
followAnimated:(BOOL)followAnimated {
[self createOverlayViewArrOnTopView:customViewArr
animated:animated
followAnimated:followAnimated];
}
- (void)createOverlayViewArrOnTopView:(NSArray<UIView *> *)overlayViewArr
animated:(BOOL)animated
followAnimated:(BOOL)followAnimated{
if ([self isEmptyArray:overlayViewArr]) {
return;
}
if (followAnimated == true) {
[self.followArr addObjectsFromArray:overlayViewArr];
}
if (animated == false) {
_customArr = [NSArray arrayWithArray:overlayViewArr];
}else{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PhotoBrowserAnimateTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
for (UIView *view in overlayViewArr) {
[self.view addSubview:view];
}
});
}
}
- (void)customViewSubViewsWillShow{
if ([self isEmptyArray:self.followArr] == false) {
for (UIView *subView in self.followArr) {
[subView setAlpha:1];
}
}
if (_isNeedFollowAnimated == true) {
[_numView setAlpha:1];
[_pageControl setAlpha:1];
[_operationBtn setAlpha:1];
}
}
- (void)customViewSubViewsWillDismiss{
if ([self isEmptyArray:self.followArr] == false) {
for (UIView *subView in self.followArr) {
[subView setAlpha:0.0];
}
}
if (_isNeedFollowAnimated == true) {
[_numView setAlpha:0.0];
[_pageControl setAlpha:0.0];
[_operationBtn setAlpha:0.0];
}
}
/**
photoBrowser dismiss with animated
@param tempView tempView
@param items current items
*/
- (void)photoBrowserWillDismissWithAnimated:(UIImageView *)tempView items:(KNPhotoItems *)items{
[_pageControl setHidden:true];
[_numView setHidden:true];
if(tempView.image == nil){
_isDismissed = true;
[self loadScreenPortrait];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self->_collectionView.alpha = 0.f;
} completion:^(BOOL finished) {
[self showStatusBar];
self->_startFrame = CGRectZero;
[self dismissViewControllerAnimated:false completion:nil];
}];
});
return;
}
UIView *sourceView = items.sourceView;
UIWindow *window = [UIApplication sharedApplication].keyWindow;
__block CGRect rect = [sourceView convertRect:[sourceView bounds] toView:window];
[self->_collectionView setHidden:true];
if([self isOutOfScreen:rect]){
if(isPortrait == true){
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[tempView setAlpha:0.f];
} completion:^(BOOL finished) {
[tempView removeFromSuperview];
[self showStatusBar];
self->_startFrame = CGRectZero;
[self dismissViewControllerAnimated:true completion:nil];
}];
}else{
_isDismissed = true;
[self loadScreenPortrait];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[tempView setAlpha:0.f];
} completion:^(BOOL finished) {
[tempView removeFromSuperview];
[self showStatusBar];
self->_startFrame = CGRectZero;
[self dismissViewControllerAnimated:true completion:nil];
}];
});
}
}else{
CGFloat width = tempView.image.size.width;
CGFloat height = tempView.image.size.height;
CGSize tempRectSize = (CGSize){PBViewWidth,(height * PBViewWidth / width) > PBViewHeight ? PBViewHeight:(height * PBViewWidth / width)};
if(isPortrait == true){
[tempView setBounds:(CGRect){CGPointZero,{tempRectSize.width,tempRectSize.height}}];
[tempView setCenter:[self.view center]];
NSLog(@"%@",NSStringFromCGRect(tempView.frame));
if(!CGRectEqualToRect(self.startFrame, CGRectZero)){
if(items.isVideo == true) {
tempView.frame = CGRectMake(self.startFrame.origin.x, self.startFrame.origin.y, tempRectSize.width, tempRectSize.height);
}else {
tempView.frame = self.startFrame;
}
}
[window addSubview:tempView];
NSLog(@"tempViewFrame===> %@ ---- %@",NSStringFromCGRect(tempView.frame),NSStringFromCGRect(self.startFrame));
self->_startFrame = CGRectZero;
[self dismissViewControllerAnimated:false completion:nil];
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[tempView setFrame:rect];
} completion:^(BOOL finished) {
[self showStatusBar];
[UIView animateWithDuration:0.15 animations:^{
[tempView setAlpha:0.f];
} completion:^(BOOL finished) {
[tempView removeFromSuperview];
}];
}];
}else{
_isDismissed = true;
[self loadScreenPortrait];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
rect = [sourceView convertRect:[sourceView bounds] toView:window];
[tempView setBounds:(CGRect){CGPointZero,{tempRectSize.width,tempRectSize.height}}];
[tempView setCenter:[self.view center]];
[window addSubview:tempView];
self->_startFrame = CGRectZero;
[self dismissViewControllerAnimated:true completion:nil];
[UIView animateWithDuration:PhotoBrowserAnimateTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[tempView setFrame:rect];
} completion:^(BOOL finished) {
[self showStatusBar];
[UIView animateWithDuration:0.15 animations:^{
[tempView setAlpha:0.f];
} completion:^(BOOL finished) {
[tempView removeFromSuperview];
}];
}];
});
}
}
}
- (BOOL)isOutOfScreen:(CGRect)rect{
if(isPortrait){
if(rect.origin.y > ScreenHeight ||
rect.origin.y <= - rect.size.height ||
rect.origin.x > ScreenWidth ||
rect.origin.x <= - rect.size.width ){
return true;
}
}else{
if(rect.origin.y > ScreenWidth ||
rect.origin.y <= - rect.size.height ||
rect.origin.x > ScreenHeight ||
rect.origin.x <= - rect.size.width){
return true;
}
}
return false;
}
/// let screen to portrait
- (void)loadScreenPortrait{
if(isPortrait) return;
NSNumber *resetOrientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationUnknown];
[[UIDevice currentDevice] setValue:resetOrientationTarget forKey:@"orientation"];
NSNumber *orientationTarget = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:orientationTarget forKey:@"orientation"];
}
- (void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
[self layoutCollectionViewAndLayout];
if ([_delegate respondsToSelector:@selector(photoBrowserWillLayoutSubviews)]) {
[_delegate photoBrowserWillLayoutSubviews];
}
}
- (void)layoutCollectionViewAndLayout{
[_layout setItemSize:(CGSize){PBViewWidth + 20,PBViewHeight}];
_layout.minimumInteritemSpacing = 0;
_layout.minimumLineSpacing = 0;
[_collectionView setFrame:(CGRect){{-10,0},{PBViewWidth + 20,PBViewHeight}}];
[_collectionView setCollectionViewLayout:_layout];
_imageView.frame = (CGRect){{-10,0},{PBViewWidth + 20,PBViewHeight}};
_progressHUD.center = self.view.center;
CGFloat y = 25;
CGFloat x = 0;
if(PBDeviceHasBang){
y = 45;
}
if(!isPortrait){
y = 15;
x = 35;
}
[_numView setFrame:(CGRect){{0,y},{PBViewWidth,25}}];
[_pageControl setFrame:(CGRect){{0,PBViewHeight - 50},{PBViewWidth,30}}];
[_operationBtn setFrame:(CGRect){{PBViewWidth - 35 - 15 - x,y},{35,20}}];
if(_offsetPageIndex){
[_collectionView setContentOffset:(CGPoint){_layout.itemSize.width * _offsetPageIndex,0} animated:false];
}
if(!_isShowed){
[self photoBrowserWillShowWithAnimated];
_isShowed = true;
}
}
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
[super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
[_collectionView.collectionViewLayout invalidateLayout];
}
/**
ApplicationWillChangeStatusBarOrientation -> Notification
*/
- (void)deviceWillOrientation{
KNPhotoItems *item = self.itemsArr[_currentIndex];
NSString *url = item.url;
if(![item.url.lastPathComponent.pathExtension.lowercaseString isEqualToString:@"gif"] && item.isVideo == false){
[_collectionView setHidden:true];
[_imageView setHidden:false];
[_progressHUD setHidden:false];
UIImageView *tempView = [self tempViewFromSourceViewWithCurrentIndex:_currentIndex];
[_imageView imageWithUrl:[NSURL URLWithString:url]
progressHUD:_progressHUD
placeHolder:tempView.image
photoItem:item];
}else{
[_collectionView setHidden:false];
}
_offsetPageIndex = _collectionView.contentOffset.x / _layout.itemSize.width;
}
/**
ApplicationDidChangeStatusBarOrientation -> Notification
*/
- (void)deviceDidOrientation{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self->_imageView setHidden:true];
[self->_progressHUD setHidden:true];
[self->_collectionView setHidden:false];
});
}
/**
right top Btn Did click
*/
- (void)operationBtnIBAction{
if ([_delegate respondsToSelector:@selector(photoBrowser:rightBtnOperationActionWithIndex:)]) {
[_delegate photoBrowser:self rightBtnOperationActionWithIndex:_currentIndex];
}
}
/**
save image to the location --> for example
@param image image
@param error error
@param contextInfo context
*/
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
__weak typeof(self) weakself = self;
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateSaveFailure
progress:0.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateSaveSuccess
progress:1.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
});
}
}
/**
save gif image to location --> for example
@param photoData data
*/
- (void)savePhotoToLocation:(NSData *)photoData url:(NSString *)url{
__weak typeof(self) weakself = self;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetResourceCreationOptions *options = [[PHAssetResourceCreationOptions alloc] init];
options.shouldMoveFile = true;
PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset];
[request addResourceWithType:PHAssetResourceTypePhoto data:photoData options:options];
request.creationDate = [NSDate date];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if(success){
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateSuccess
progress:1.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
}else if(error) {
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateFailure
progress:0.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
}
});
}];
});
}
/**
remove current image or video on photobrowser
*/
- (void)removeImageOrVideoOnPhotoBrowser{
KNPhotoItems *item = _itemsArr[_currentIndex];
if (item.isVideo) {
NSIndexPath *path = [NSIndexPath indexPathForRow:_currentIndex inSection:0];
KNPhotoVideoCell *cell = (KNPhotoVideoCell *)[_collectionView cellForItemAtIndexPath:path];
[cell playerWillEndDisplay];
}
NSMutableArray *tempArr = [NSMutableArray arrayWithArray:_itemsArr];
[tempArr removeObjectAtIndex:_currentIndex];
_itemsArr = [tempArr copy];
[_collectionView reloadData];
if(_itemsArr.count == 0){
[_collectionView setHidden:true];
[_operationBtn setHidden:true];
[_pageControl setHidden:true];
[_numView setHidden:true];
[self setNeedsStatusBarAppearanceUpdate];
if([_delegate respondsToSelector:@selector(photoBrowser:willDismissWithIndex:)]){
[_delegate photoBrowser:self willDismissWithIndex:_currentIndex];
}
[self dismissViewControllerAnimated:true completion:nil];
}else{
[_pageControl setCurrentPage:_currentIndex];
[_pageControl setNumberOfPages:_itemsArr.count];
[_numView setCurrentNum:(_currentIndex + 1) totalNum:_itemsArr.count];
}
if ([_delegate respondsToSelector:@selector(photoBrowser:removeSourceWithRelativeIndex:)]) {
[_delegate photoBrowser:self removeSourceWithRelativeIndex:_currentIndex];
}
if ([_delegate respondsToSelector:@selector(photoBrowser:removeSourceWithAbsoluteIndex:)]) {
[_delegate photoBrowser:self removeSourceWithAbsoluteIndex:[_tempArr indexOfObject:item]];
}
}
/**
download photo or video to Album, but it must be authed at first
*/
- (void)downloadImageOrVideoToAlbum{
KNPhotoItems *items = self.itemsArr[self.currentIndex];
__weak typeof(self) weakself = self;
if (items.isVideo) { // video
if ([items.url hasPrefix:@"http"]) {
KNPhotoDownloadFileMgr *fileMgr = [[KNPhotoDownloadFileMgr alloc] init];
if ([fileMgr startCheckIsExistVideo:items]) { // video is exist
NSString *filePath = [fileMgr startGetFilePath:items];
UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}else { // downloading
self.downloadMgr = [[KNPhotoDownloadMgr shareInstance] init];
if (weakself.isNeedOnlinePlay == true) {
[self.downloadMgr downloadVideoWithPhotoItems:items downloadBlock:^(KNPhotoDownloadState downloadState, float progress) {
if (downloadState == KNPhotoDownloadStateSuccess) {
NSString *filePath = [fileMgr startGetFilePath:items];
UISaveVideoAtPathToSavedPhotosAlbum(filePath, weakself, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}else if (downloadState == KNPhotoDownloadStateDownloading){
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:downloadState
progress:progress
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
});
}
}];
}else {
KNPhotoVideoCell *cell = (KNPhotoVideoCell *)[weakself.collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:weakself.currentIndex inSection:0]];
[cell.locatePlayerView playerDownloadBlock:^(KNPhotoDownloadState downloadState, float progress) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:downloadState
progress:progress
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
});
if (downloadState == KNPhotoDownloadStateSuccess) {
NSString *filePath = [fileMgr startGetFilePath:items];
UISaveVideoAtPathToSavedPhotosAlbum(filePath, weakself, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}
}];
}
}
}else {
UISaveVideoAtPathToSavedPhotosAlbum(items.url, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
}
}else{ // image
if(items.url){ // net image
SDImageCache *cache = [SDImageCache sharedImageCache];
SDWebImageManager *mgr = [SDWebImageManager sharedManager];
[cache diskImageExistsWithKey:items.url completion:^(BOOL isInCache) {
if(!isInCache){
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateUnknow
progress:0.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
}else{
[[mgr imageCache] queryImageForKey:items.url options:SDWebImageQueryMemoryData | SDWebImageRetryFailed context:nil completion:^(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType) {
if([image images] != nil){
[weakself savePhotoToLocation:data url:items.url];
}else{
if(image){
dispatch_async(dispatch_get_main_queue(), ^{
UIImageWriteToSavedPhotosAlbum(image, weakself, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
});
}
}
}];
}
}];
}else{ // locate image or sourceimage
UIImageView *imageView = [self tempViewFromSourceViewWithCurrentIndex:self.currentIndex];
if(imageView.image){
dispatch_async(dispatch_get_main_queue(), ^{
UIImageWriteToSavedPhotosAlbum(imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), NULL);
});
}else{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateFailure
progress:0.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
}
}
}
}
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
__weak typeof(self) weakself = self;
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateSaveFailure
progress:0.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
if ([weakself.delegate respondsToSelector:@selector(photoBrowser:state:progress:photoItemRelative:photoItemAbsolute:)]) {
[weakself.delegate photoBrowser:weakself
state:KNPhotoDownloadStateSaveSuccess
progress:1.0
photoItemRelative:weakself.itemsArr[weakself.currentIndex]
photoItemAbsolute:weakself.tempArr[weakself.currentIndex]];
}
});
}
}
/// cancen download video when downloading
- (void)cancelVideoDownload{
[self.downloadMgr cancelTask];
}
/**
player's rate immediately to use
*/
- (void)setImmediatelyPlayerRate:(CGFloat)rate {
if (rate < 0.5 || rate > 2.0) {
return;
}
KNPhotoItems *items = self.itemsArr[_currentIndex];
if (items.isVideo) {
KNPhotoVideoCell *cell = (KNPhotoVideoCell *)[_collectionView cellForItemAtIndexPath:[NSIndexPath indexPathForRow:_currentIndex inSection:0]];
if (_isNeedOnlinePlay) {
[cell.onlinePlayerView playerRate:rate];
}else {
[cell.locatePlayerView playerRate:rate];
}
}
}
/**
longPress Did click
*/
- (void)longPressIBAction{
if(!_isNeedLongPress) return;
if ([_delegate respondsToSelector:@selector(photoBrowser:imageLongPressWithIndex:)]) {
[_delegate photoBrowser:self imageLongPressWithIndex:_currentIndex];
}
}
/// create one image by Color
/// @param imageColor color
/// @param size image size
- (UIImage *)createImageWithUIColor:(UIColor *)imageColor size:(CGSize)size{
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [imageColor CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
/**
get the first image of GIF
@param data data
@return image
*/
- (UIImage *)imageFromGifFirstImage:(NSData *)data{
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
size_t count = CGImageSourceGetCount(source);
UIImage *sourceImage;
if(count <= 1){
CFRelease(source);
sourceImage = [[UIImage alloc] initWithData:data];
}else{
CGImageRef image = CGImageSourceCreateImageAtIndex(source, 0, NULL);
sourceImage = [UIImage imageWithCGImage:image];
CFRelease(source);
CGImageRelease(image);
}
return sourceImage;
}
/**
judge array is empty or null or nil
@param array isEmpty array
*/
- (BOOL)isEmptyArray:(NSArray *)array{
if(array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0){
return true;
}
return false;
}
/// judge string is empty or null or nil
/// @param string isEmpty string
- (BOOL)isEmptyString:(NSString *)string{
if(string == nil || string == NULL || [string isKindOfClass:[NSNull class]] || [[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]==0){
return true;
}
return false;
}
/**
get the image of current sourceView
@param currentIndex index
@return imageView with image
*/
- (UIImageView *)tempViewFromSourceViewWithCurrentIndex:(NSInteger)currentIndex{
UIImageView *imageView = [[UIImageView alloc] init];
KNPhotoItems *items = _itemsArr[currentIndex];
// if it is not custom sourceView, just UIImageView or UIButton
if ([self isEmptyArray:items.sourceLinkArr]) {
if([items.sourceView isKindOfClass:[UIImageView class]]){
imageView.image = [(UIImageView *)items.sourceView image];
}else if ([items.sourceView isKindOfClass:[UIButton class]]){
UIButton *btn = (UIButton *)items.sourceView;
[imageView setImage:[btn currentBackgroundImage]?[btn currentBackgroundImage]:[btn currentImage]];
}
}else { // custom sourceView , it must set sourceLinkArr and sourceLinkProperyName
UIView *currentView = items.sourceView;
for (NSInteger i = 0; i < items.sourceLinkArr.count; i++) {
Class cls = NSClassFromString(items.sourceLinkArr[i]);
for (NSInteger j = 0; j < currentView.subviews.count; j++) {
if ([currentView.subviews[j] isKindOfClass:cls]) {
currentView = currentView.subviews[j];
break;
}
}
}
NSString *lastType = items.sourceLinkArr.lastObject;
if ([lastType isEqualToString:@"UIImageView"] && [currentView isKindOfClass:[UIImageView class]]) {
imageView.image = [(UIImageView *)currentView image];
}else if ([lastType isEqualToString:@"UIButton"] && [currentView isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)currentView;
[imageView setImage:[btn currentBackgroundImage]?[btn currentBackgroundImage]:[btn currentImage]];
}else {
if ([self isEmptyString:items.sourceLinkProperyName] == false) { // get all propertyName of currentView's class
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([currentView class], &count);
for (NSInteger i = 0; i < count; i++) {
struct objc_property *objc_property = propertyList[i];
NSString *property = [NSString stringWithFormat:@"%s",property_getName(objc_property)];
if ([property isEqualToString:items.sourceLinkProperyName]) {
[imageView setImage:[currentView valueForKey:items.sourceLinkProperyName]];
}
}
free(propertyList);
}
}
}
if(items.sourceView == nil && imageView.image == nil && items.sourceImage != nil){
imageView.image = items.sourceImage;
}
if(imageView.image == nil){
if (items.isVideo == false) {
if (items.url) {
UIColor *imageColor = self.placeHolderColor ? self.placeHolderColor : UIColor.clearColor;
CGSize size = CGSizeMake(PBViewWidth, PBViewWidth);
imageView.image = [self createImageWithUIColor: imageColor size: size];
}else {
imageView.image = [self createImageWithUIColor: UIColor.clearColor size: CGSizeMake(PBViewWidth, PBViewWidth)];
}
}else {
if (items.videoPlaceHolderImageUrl) {
UIColor *imageColor = self.placeHolderColor ? self.placeHolderColor : UIColor.clearColor;
CGSize size = CGSizeMake(PBViewWidth, PBViewWidth);
imageView.image = [self createImageWithUIColor: imageColor size: size];
}else {
imageView.image = [self createImageWithUIColor: UIColor.clearColor size: CGSizeMake(PBViewWidth, PBViewWidth)];
}
}
}
return imageView;
}
@end
@implementation KNPhotoItems
@end
@implementation UIDevice(PBExtension)
/**
judge is have auth of Album --> for example
@param authorBlock block
*/
+ (void)deviceAlbumAuth:(void (^)(BOOL isAuthor))authorBlock{
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusRestricted) {
if(authorBlock){
authorBlock(false);
}
} else if (status == PHAuthorizationStatusDenied) {
if(authorBlock){
authorBlock(false);
}
} else if (status == PHAuthorizationStatusAuthorized) {
if(authorBlock){
authorBlock(true);
}
} else if (status == PHAuthorizationStatusNotDetermined) {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized) {
dispatch_async(dispatch_get_main_queue(), ^{
if(authorBlock){
authorBlock(true);
}
});
}else{
dispatch_async(dispatch_get_main_queue(), ^{
if(authorBlock){
authorBlock(false);
}
});
}
}];
}
}
/// device shake
+ (void)deviceShake{
AudioServicesPlaySystemSound(1520);
}
@end