Лучший способ перехода между двумя изображениями в UIImageView

Я реализовал довольно простую программу просмотра изображений, которая позволяет пользователю просматривать коллекцию изображений. Они загружаются из Интернета и отображаются на устройстве через объект UIImageView. Что-то вроде этого:

UIImage *image = [[UIImage alloc] initWithData:imageData];
[img setImage:image];

imageData - это экземпляр NSData, который я использую для загрузки содержимого изображения из URL-адреса, а img - это экземпляр UIImageView.

Все работает хорошо, но новое изображение заменяет то, которое отображалось раньше, без каких-либо переходов, и мне было интересно, есть ли простой способ сделать хороший переход анимации для улучшения взаимодействия с пользователем.

есть идеи как это сделать? Будем очень признательны за образцы кода.


person Community    schedule 17.10.2008    source источник
comment
Для тех из нас, кто пролистывает, было бы здорово, если бы кто-нибудь мог выбрать ответ. Поскольку этот пользователь, похоже, как-то ушел ...   -  person Mytheral    schedule 13.09.2011


Ответы (6)


Я как раз просматривал ваш пост и имел точно такое же требование. Проблема со всеми вышеперечисленными решениями заключается в том, что вам придется включить логику перехода в свой контроллер. В том смысле, что подход не модульный. Вместо этого я написал этот подкласс UIImageView:

Файл TransitionImageView.h:

#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

#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

Вы даже можете переопределить -setImage метод UIImageView и вызвать мой -setImage:withTransitionAnimation: метод. Если это сделано таким образом, убедитесь, что вы вызываете [super setImage:] вместо [self setImage:] в методе -setImage:withTransitionAnimation:, чтобы он не закончился бесконечным рекурсивным вызовом!

-Радж

person Raj Pawan Gumdal    schedule 23.08.2010

Хитрость в том, что вы создаете два экземпляра UIImageView. Вы меняете их местами между вызовами UIView + beginAnimations и + commitAnimations.

person Chris Lundie    schedule 17.10.2008

Пожалуйста, проверьте ответ. Думаю, вы это ищете:

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];
person Manab Kumar Mal    schedule 11.06.2014
comment
Это хорошо работает, особенно с подтипами push и transition. Я думаю, что это оптимальный ответ, поскольку он не требует создания каких-либо фальшивых дополнительных представлений или манипулирования их геометрией. - person SG1; 09.10.2014

Ничего не отличается от того, что было объяснено, но в коде доступны следующие переходы:

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

Код (поместите это в обратный вызов, например, 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];
person Rob    schedule 09.12.2008

Есть несколько способов сделать это, и я согласен с тем, что Ben View Transitions - отличный пример. Если вы ищете простые полноэкранные переходы, я бы просто подумал о запуске нового служебного приложения и взглянул на метод toggleView в RootViewController.m. Попробуйте переключить UIViewAnimationTransitionFlipFromLeft и UIViewAnimationTransitionFlipFromRight на UIViewAnimationTransitionCurlUp и UIViewAnimationTransitionCurlDown для действительно хорошего эффекта перехода (это работает только на устройстве).

person Jamey McElveen    schedule 21.10.2008

вот что я сделал: исчезновение. Я помещаю еще один UIImageView с тем же UIImage и размером, называемым tmp. я заменяю UIImage базового UIImageView. Затем я положил нужное изображение на основу (все еще покрытое tmp).

Следующий шаг - установить альфа tmp равным нулю, - растянуть базовый UIImageView к правому соотношению нового UIImage на основе высоты базы.

Вот код:

    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];
person Community    schedule 09.06.2009