RCAnimatedImagesView.m 5.94 KB
//
//  RCAnimatedImagesView.m
//  RCloudMessage
//
//  Created by 杜立召 on 15/3/18.
//  Copyright (c) 2015年 RongCloud. All rights reserved.
//

#import "RCAnimatedImagesView.h"

#define noImageDisplayingIndex -1
#define imageSwappingAnimationDuration 2.0f

#define imageViewsBorderOffset 150

@interface RCAnimatedImagesView()
{
    BOOL animating;
    NSUInteger totalImages;
    NSUInteger currentlyDisplayingImageViewIndex;
    NSInteger currentlyDisplayingImageIndex;
}

@property (nonatomic, retain) NSArray *imageViews;
@property (nonatomic, retain) NSTimer *imageSwappingTimer;

- (void)_init;

+ (NSUInteger)randomIntBetweenNumber:(NSUInteger)minNumber andNumber:(NSUInteger)maxNumber;
@end

@implementation RCAnimatedImagesView

@synthesize imageViews = _imageViews;
@synthesize imageSwappingTimer = _imageSwappingTimer;

@synthesize delegate = _delegate,
timePerImage = _timePerImage;

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if ((self = [super initWithCoder:aDecoder]))
    {
        [self _init];
    }
    
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    if ((self = [super initWithFrame:frame]))
    {
        [self _init];
    }
    
    return self;
}

- (void)_init
{
    NSMutableArray *imageViews = [NSMutableArray array];
    
    for (int i = 0; i < 2; i++)
    {
        UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(-imageViewsBorderOffset*3.3, -imageViewsBorderOffset, self.bounds.size.width + (imageViewsBorderOffset * 2), self.bounds.size.height + (imageViewsBorderOffset * 2))];
        imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        imageView.contentMode = UIViewContentModeScaleAspectFill;
        imageView.clipsToBounds = NO;
        [self addSubview:imageView];
        
        [imageViews addObject:imageView];
    }
    
    self.imageViews = [imageViews copy];
    
    currentlyDisplayingImageIndex = noImageDisplayingIndex;
}


- (void)startAnimating
{
    
    if (!animating)
    {
        animating = YES;
        [self.imageSwappingTimer fire];
    }
}

- (void)bringNextImage
{
    
    UIImageView *imageViewToHide = [self.imageViews objectAtIndex:currentlyDisplayingImageViewIndex];
    
    currentlyDisplayingImageViewIndex = currentlyDisplayingImageViewIndex == 0 ? 1 : 0;
    
    UIImageView *imageViewToShow = [self.imageViews objectAtIndex:currentlyDisplayingImageViewIndex];
    
    NSUInteger nextImageToShowIndex = currentlyDisplayingImageIndex;
    
    do
    {
        nextImageToShowIndex = [[self class] randomIntBetweenNumber:0 andNumber:totalImages-1];
    }
    while (nextImageToShowIndex == currentlyDisplayingImageIndex);
    
    currentlyDisplayingImageIndex = nextImageToShowIndex;
    
    imageViewToShow.image = [self.delegate animatedImagesView:self imageAtIndex:nextImageToShowIndex];
    
    static const CGFloat kMovementAndTransitionTimeOffset = 0.1;
    
    [UIView animateWithDuration:self.timePerImage + imageSwappingAnimationDuration + kMovementAndTransitionTimeOffset delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveLinear animations:^{
        NSInteger randomTranslationValueX = imageViewsBorderOffset*3.5-[[self class] randomIntBetweenNumber:0 andNumber:imageViewsBorderOffset];
        NSInteger randomTranslationValueY = 0;
        
        CGAffineTransform translationTransform = CGAffineTransformMakeTranslation(randomTranslationValueX, randomTranslationValueY);
        
        CGFloat randomScaleTransformValue = [[self class] randomIntBetweenNumber:115 andNumber:120]/100;
        
        CGAffineTransform scaleTransform = CGAffineTransformMakeScale(randomScaleTransformValue, randomScaleTransformValue);
        
        imageViewToShow.transform = CGAffineTransformConcat(scaleTransform, translationTransform);
    } completion:NULL];
    
    [UIView animateWithDuration:imageSwappingAnimationDuration delay:kMovementAndTransitionTimeOffset options:UIViewAnimationOptionBeginFromCurrentState
     | UIViewAnimationCurveLinear animations:^{
         imageViewToShow.alpha = 1.0;
         imageViewToHide.alpha = 0.0;
     } completion:^(BOOL finished) {
         if (finished)
         {
             imageViewToHide.transform = CGAffineTransformIdentity;
         }
     }];
}

- (void)reloadData
{
    totalImages = [self.delegate animatedImagesNumberOfImages:self];
    
    [self.imageSwappingTimer fire];
}

- (void)stopAnimating
{
    if (animating)
    {
        [_imageSwappingTimer invalidate];
        _imageSwappingTimer = nil;
        
        [UIView animateWithDuration:imageSwappingAnimationDuration delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
            for (UIImageView *imageView in self.imageViews)
            {
                imageView.alpha = 1;
            }
        } completion:^(BOOL finished) {
            currentlyDisplayingImageIndex = noImageDisplayingIndex;
            animating = NO;
        }];
    }
}


- (NSTimeInterval)timePerImage
{
    if (_timePerImage == 0)
    {
        return kJSAnimatedImagesViewDefaultTimePerImage;
    }
    
    return _timePerImage;
}

- (void)setDelegate:(id<RCAnimatedImagesViewDelegate>)delegate
{
    if (delegate != _delegate)
    {
        _delegate = delegate;
        totalImages = [_delegate animatedImagesNumberOfImages:self];
    }
}


- (NSTimer *)imageSwappingTimer
{
    if (!_imageSwappingTimer)
    {
        _imageSwappingTimer = [NSTimer scheduledTimerWithTimeInterval:self.timePerImage target:self selector:@selector(bringNextImage) userInfo:nil repeats:YES];
    }
    
    return _imageSwappingTimer;
}


+ (NSUInteger)randomIntBetweenNumber:(NSUInteger)minNumber andNumber:(NSUInteger)maxNumber
{
    if (minNumber > maxNumber) {
        return [self randomIntBetweenNumber:maxNumber andNumber:minNumber];
    }
    
    NSUInteger i = (arc4random() % (maxNumber - minNumber + 1)) + minNumber;
    
    return i;
}

#pragma mark - Memory Management

- (void)dealloc
{
    [_imageSwappingTimer invalidate];
}

@end