You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

272 lines
10 KiB

//
// XHImageViewer.m
// XHImageViewer
//
// Created by 曾 宪华 on 14-2-17.
// Copyright (c) 2014年 曾宪华 开发团队(http://iyilunba.com ) 本人QQ:543413507 本人QQ群(142557668). All rights reserved.
//
#import "XHImageViewer.h"
#import "XHViewState.h"
#import "XHZoomingImageView.h"
@implementation XHObject
@end
@interface XHImageViewer ()
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) NSArray *imgViews;
@end
@implementation XHImageViewer
- (id)init {
self = [self initWithFrame:CGRectZero];
if (self) {
[self _setup];
}
return self;
}
- (void)_setup {
self.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1];
self.backgroundScale = 0.95;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)];
pan.maximumNumberOfTouches = 1;
[self addGestureRecognizer:pan];
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:[[UIScreen mainScreen] bounds]];
if (self) {
[self _setup];
}
return self;
}
- (void)setImageViewsFromArray:(NSArray*)views {
NSMutableArray *imgViews = [NSMutableArray array];
for(id obj in views) {
if([obj isKindOfClass:[UIImageView class]]) {
[imgViews addObject:obj];
UIImageView *view = obj;
XHViewState *state = [XHViewState viewStateForView:view];
[state setStateWithView:view];
view.userInteractionEnabled = NO;
}
}
_imgViews = [imgViews copy];
}
- (void)showWithImageViews:(NSArray*)views selectedView:(UIImageView*)selectedView {
[self setImageViewsFromArray:views];
if(_imgViews.count > 0) {
if(![selectedView isKindOfClass:[UIImageView class]] || ![_imgViews containsObject:selectedView]){
selectedView = _imgViews[0];
}
[self showWithSelectedView:selectedView];
}
}
#pragma mark- Properties
- (void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:[backgroundColor colorWithAlphaComponent:0]];
}
- (NSInteger)pageIndex {
return (_scrollView.contentOffset.x / _scrollView.frame.size.width + 0.5);
}
#pragma mark- View management
- (UIImageView *)currentView {
return [_imgViews objectAtIndex:self.pageIndex];
}
- (void)showWithSelectedView:(UIImageView *)selectedView {
[self.scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
const NSInteger currentPage = [_imgViews indexOfObject:selectedView];
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
if(_scrollView == nil) {
_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_scrollView.pagingEnabled = YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.backgroundColor = [self.backgroundColor colorWithAlphaComponent:1];
_scrollView.alpha = 0;
}
[self addSubview:_scrollView];
[window addSubview:self];
const CGFloat fullW = window.frame.size.width;
const CGFloat fullH = window.frame.size.height;
selectedView.frame = [window convertRect:selectedView.frame fromView:selectedView.superview];
[window addSubview:selectedView];
[UIView animateWithDuration:0.3
animations:^{
_scrollView.alpha = 1;
window.rootViewController.view.transform = CGAffineTransformMakeScale(self.backgroundScale, self.backgroundScale);
selectedView.transform = CGAffineTransformIdentity;
CGSize size = (selectedView.image) ? selectedView.image.size : selectedView.frame.size;
CGFloat ratio = MIN(fullW / size.width, fullH / size.height);
CGFloat W = ratio * size.width;
CGFloat H = ratio * size.height;
selectedView.frame = CGRectMake((fullW-W)/2, (fullH-H)/2, W, H);
}
completion:^(BOOL finished) {
_scrollView.contentSize = CGSizeMake(_imgViews.count * fullW, 0);
_scrollView.contentOffset = CGPointMake(currentPage * fullW, 0);
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedScrollView:)];
[_scrollView addGestureRecognizer:gesture];
for(UIImageView *view in _imgViews){
view.transform = CGAffineTransformIdentity;
CGSize size = (view.image) ? view.image.size : view.frame.size;
CGFloat ratio = MIN(fullW / size.width, fullH / size.height);
CGFloat W = ratio * size.width;
CGFloat H = ratio * size.height;
view.frame = CGRectMake((fullW-W)/2, (fullH-H)/2, W, H);
XHZoomingImageView *tmp = [[XHZoomingImageView alloc] initWithFrame:CGRectMake([_imgViews indexOfObject:view] * fullW, 0, fullW, fullH)];
tmp.imageView = view;
[_scrollView addSubview:tmp];
}
}
];
}
- (void)prepareToDismiss {
UIImageView *currentView = [self currentView];
if([self.delegate respondsToSelector:@selector(imageViewer:willDismissWithSelectedView:)]) {
[self.delegate imageViewer:self willDismissWithSelectedView:currentView];
}
for(UIImageView *view in _imgViews) {
if(view != currentView) {
XHViewState *state = [XHViewState viewStateForView:view];
view.transform = CGAffineTransformIdentity;
view.frame = state.frame;
view.transform = state.transform;
[state.superview addSubview:view];
}
}
}
- (void)dismissWithAnimate {
UIView *currentView = [self currentView];
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
CGRect rct = currentView.frame;
currentView.transform = CGAffineTransformIdentity;
currentView.frame = [window convertRect:rct fromView:currentView.superview];
[window addSubview:currentView];
[UIView animateWithDuration:0.3
animations:^{
_scrollView.alpha = 0;
window.rootViewController.view.transform = CGAffineTransformIdentity;
XHViewState *state = [XHViewState viewStateForView:currentView];
currentView.frame = [window convertRect:state.frame fromView:state.superview];
currentView.transform = state.transform;
if([self.delegate respondsToSelector:@selector(imageViewer:willdidDismissWithSelectedView:)]) {
[self.delegate imageViewer:self willdidDismissWithSelectedView:[self currentView]];
}
}
completion:^(BOOL finished) {
if([self.delegate respondsToSelector:@selector(imageViewer:didDismissWithSelectedView:)]) {
[self.delegate imageViewer:self didDismissWithSelectedView:[self currentView]];
}
XHViewState *state = [XHViewState viewStateForView:currentView];
currentView.transform = CGAffineTransformIdentity;
currentView.frame = state.frame;
currentView.transform = state.transform;
[state.superview addSubview:currentView];
for (UIView *view in _imgViews) {
XHViewState *_state = [XHViewState viewStateForView:view];
view.userInteractionEnabled = _state.userInteratctionEnabled;
}
[self removeFromSuperview];
}
];
}
#pragma mark- Gesture events
- (void)tappedScrollView:(UITapGestureRecognizer *)sender {
[self prepareToDismiss];
[self dismissWithAnimate];
}
- (void)didPan:(UIPanGestureRecognizer *)sender {
static UIImageView *currentView = nil;
if(sender.state == UIGestureRecognizerStateBegan) {
currentView = [self currentView];
UIView *targetView = currentView.superview;
while(![targetView isKindOfClass:[XHZoomingImageView class]]) {
targetView = targetView.superview;
}
if (((XHZoomingImageView *)targetView).isViewing) {
currentView = nil;
} else {
UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
currentView.frame = [window convertRect:currentView.frame fromView:currentView.superview];
[window addSubview:currentView];
[self prepareToDismiss];
}
}
if(currentView) {
if(sender.state == UIGestureRecognizerStateEnded) {
if(_scrollView.alpha>0.5) {
[self showWithSelectedView:currentView];
} else {
[self dismissWithAnimate];
}
currentView = nil;
} else {
CGPoint p = [sender translationInView:self];
CGAffineTransform transform = CGAffineTransformMakeTranslation(0, p.y);
transform = CGAffineTransformScale(transform, 1 - fabs(p.y)/1000, 1 - fabs(p.y)/1000);
currentView.transform = transform;
CGFloat r = 1-fabs(p.y)/200;
_scrollView.alpha = MAX(0, MIN(1, r));
}
}
}
@end