Best way to transition between two images in a UIImageView

后端 未结 7 2315
無奈伤痛
無奈伤痛 2020-12-13 00:01

I have implemented a pretty simple picture viewer that will allow the user to browse through a collection of images. They are loaded from the Internet, and displayed on the

相关标签:
7条回答
  • 2020-12-13 00:08

    I was just going through your post and had exactly the same requirement. The problem with all above solutions is, you will have to incorporate the logic of transition into your controller. In the sense the approach is not modular. Instead I wrote this subclass of UIImageView:

    TransitionImageView.h file:

    #import <UIKit/UIKit.h>
    
    
    @interface TransitionImageView : UIImageView 
    {
        UIImageView *mOriginalImageViewContainerView;
        UIImageView *mIntermediateTransitionView;
    }
    @property (nonatomic, retain) UIImageView *originalImageViewContainerView;
    @property (nonatomic, retain) UIImageView *intermediateTransitionView;
    
    #pragma mark -
    #pragma mark Animation methods
    -(void)setImage:(UIImage *)inNewImage withTransitionAnimation:(BOOL)inAnimation;
    
    @end
    

    TransitionImageView.m file:

    #import "TransitionImageView.h"
    
    #define TRANSITION_DURATION 1.0
    
    @implementation TransitionImageView
    @synthesize intermediateTransitionView = mIntermediateTransitionView;
    @synthesize originalImageViewContainerView = mOriginalImageViewContainerView;
    
    - (id)initWithFrame:(CGRect)frame {
        if ((self = [super initWithFrame:frame])) {
            // Initialization code
        }
        return self;
    }
    
    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    - (void)drawRect:(CGRect)rect {
        // Drawing code
    }
    */
    
    - (void)dealloc 
    {
        [self setOriginalImageViewContainerView:nil];
        [self setIntermediateTransitionView:nil];
        [super dealloc];
    }
    
    #pragma mark -
    #pragma mark Animation methods
    -(void)setImage:(UIImage *)inNewImage withTransitionAnimation:(BOOL)inAnimation
    {
        if (!inAnimation)
        {
            [self setImage:inNewImage];
        }
        else
        {
            // Create a transparent imageView which will display the transition image.
            CGRect rectForNewView = [self frame];
            rectForNewView.origin = CGPointZero;
            UIImageView *intermediateView = [[UIImageView alloc] initWithFrame:rectForNewView];
            [intermediateView setBackgroundColor:[UIColor clearColor]];
            [intermediateView setContentMode:[self contentMode]];
            [intermediateView setClipsToBounds:[self clipsToBounds]];
            [intermediateView setImage:inNewImage];
    
            // Create the image view which will contain original imageView's contents:
            UIImageView *originalView = [[UIImageView alloc] initWithFrame:rectForNewView];
            [originalView setBackgroundColor:[UIColor clearColor]];
            [originalView setContentMode:[self contentMode]];
            [originalView setClipsToBounds:[self clipsToBounds]];
            [originalView setImage:[self image]];
    
            // Remove image from the main imageView and add the originalView as subView to mainView:
            [self setImage:nil];
            [self addSubview:originalView];
    
            // Add the transparent imageView as subview whose dimensions are same as the view which holds it.
            [self addSubview:intermediateView];
    
            // Set alpha value to 0 initially:
            [intermediateView setAlpha:0.0];
            [originalView setAlpha:1.0];
            [self setIntermediateTransitionView:intermediateView];
            [self setOriginalImageViewContainerView:originalView];
            [intermediateView release];
            [originalView release];
    
            // Begin animations:
            [UIView beginAnimations:@"ImageViewTransitions" context:nil];
            [UIView setAnimationDuration:(double)TRANSITION_DURATION];
            [UIView setAnimationDelegate:self];
            [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
            [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
            [[self intermediateTransitionView] setAlpha:1.0];
            [[self originalImageViewContainerView] setAlpha:0.0];
            [UIView commitAnimations];
        }
    }
    
    -(void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
    {
        // Reset the alpha of the main imageView
        [self setAlpha:1.0];
    
        // Set the image to the main imageView:
        [self setImage:[[self intermediateTransitionView] image]];
    
        [[self intermediateTransitionView] removeFromSuperview];
        [self setIntermediateTransitionView:nil];
    
        [[self originalImageViewContainerView] removeFromSuperview];
        [self setOriginalImageViewContainerView:nil];
    }
    
    @end
    

    You can even override the -setImage method of UIImageView and call my -setImage:withTransitionAnimation: method. If it is done like this make sure that you call [super setImage:] instead of [self setImage:] in the method -setImage:withTransitionAnimation: so that it wont end up in infinite recursive call!

    -Raj

    0 讨论(0)
  • 2020-12-13 00:08
    [UIView 
        animateWithDuration:0.2 
        delay:0 
        options:UIViewAnimationCurveEaseOut
        animations:^{
            self.view0.alpha = 0;
            self.view1.alpha = 1;
        }
        completion:^(BOOL finished){
            view0.hidden = YES;
        }
    ];
    
    0 讨论(0)
  • 2020-12-13 00:13

    Please check the answer. I think you are looking for this:

    imgvw.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"Your Image name as string"]]];
    CATransition *transition = [CATransition animation];
    transition.duration = 1.0f;
    transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    transition.type = kCATransitionFade;
    [imgvw.layer addAnimation:transition forKey:nil];
    
    0 讨论(0)
  • 2020-12-13 00:17

    Nothing different from what's been explained but in code, these are the available transitions:

    typedef enum {
            UIViewAnimationTransitionNone,
            UIViewAnimationTransitionFlipFromLeft,
            UIViewAnimationTransitionFlipFromRight,
            UIViewAnimationTransitionCurlUp,
            UIViewAnimationTransitionCurlDown,
        } UIViewAnimationTransition;
    

    Code (Put this in a callback like touchesEnded):

    CGContextRef context = UIGraphicsGetCurrentContext();
    [UIView beginAnimations:nil context:context];
    
    [UIView setAnimationTransition: UIViewAnimationTransitionFlipFromLeft forView:[self superview] cache:YES];
    
    // -- These don't work on the simulator and the curl up will turn into a fade -- //
    //[UIView setAnimationTransition: UIViewAnimationTransitionCurlUp forView:[self superview] cache:YES];
    //[UIView setAnimationTransition: UIViewAnimationTransitionCurlDown forView:[self superview] cache:YES];
    
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:1.0];
    
    // Below assumes you have two subviews that you're trying to transition between
    [[self superview] exchangeSubviewAtIndex:0 withSubviewAtIndex:1];
    [UIView commitAnimations];
    
    0 讨论(0)
  • 2020-12-13 00:18

    The trick is you make two UIImageView instances. You swap them in between calls to UIView +beginAnimations and +commitAnimations.

    0 讨论(0)
  • 2020-12-13 00:19

    here is what i have done: a fading. i put another UIImageView with the same UIImage and dimension called tmp. i replace the UIImage of the base UIImageView. Then i put the right image on the base (still covered by tmp).

    Next step is - to set alpha of tmp to zero, - to stretch the base UIImageView to right ratio of the new UIImage based on the height of the base.

    Here is the code:

        UIImage *img = [params objectAtIndex:0]; // the right image
    UIImageView *view = [params objectAtIndex:1]; // the base
    
    UIImageView *tmp = [[UIImageView alloc] initWithImage:view.image]; // the one which will use to fade
    tmp.frame = CGRectMake(0, 0, view.frame.size.width, view.frame.size.height);
    [view addSubview:tmp];
    
    view.image = img;
    float r = img.size.width / img.size.height;
    float h = view.frame.size.height;
    float w = h * r;
    float x = view.center.x - w/2;
    float y = view.frame.origin.y;
    
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    
    tmp.alpha = 0;
    view.frame = CGRectMake(x, y, w, h);
    
    [UIView commitAnimations];
    
    [tmp performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:1.5];
    [tmp performSelector:@selector(release) withObject:nil afterDelay:2];
    
    0 讨论(0)
提交回复
热议问题