【问题标题】:Best way to transition between two images in a UIImageView在 UIImageView 中的两个图像之间转换的最佳方法
【发布时间】:2010-09-17 18:45:22
【问题描述】:

我实现了一个非常简单的图片查看器,它允许用户浏览一组图片。它们从 Internet 加载,并通过UIImageView 对象显示在设备上。像这样的:

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

imageDataNSData 的一个实例,我使用它从 URL 加载图像的内容,imgUIImageView 实例。

一切都很好,但是新图像替换了之前显示的图像,没有任何过渡,我想知道是否有一种简单的方法可以进行良好的动画过渡以改善用户体验。

知道怎么做吗?代码示例将不胜感激。

【问题讨论】:

  • 对于我们这些翻阅它的人来说,如果有人可以选择答案,那就太好了。由于该用户似乎留下了一些如何...

标签: ios objective-c uiimageview


【解决方案1】:

我刚刚浏览了您的帖子,并且有完全相同的要求。以上所有解决方案的问题是,您必须将转换逻辑合并到您的控制器中。从某种意义上说,该方法不是模块化的。相反,我编写了 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

你甚至可以覆盖 UIImageView 的-setImage 方法并调用我的-setImage:withTransitionAnimation: 方法。如果这样做,请确保在方法 -setImage:withTransitionAnimation: 中调用 [super setImage:] 而不是 [self setImage:],这样它就不会以无限递归调用告终!

-拉吉

【讨论】:

    【解决方案2】:
    [UIView 
        animateWithDuration:0.2 
        delay:0 
        options:UIViewAnimationCurveEaseOut
        animations:^{
            self.view0.alpha = 0;
            self.view1.alpha = 1;
        }
        completion:^(BOOL finished){
            view0.hidden = YES;
        }
    ];
    

    【讨论】:

      【解决方案3】:

      诀窍是创建两个 UIImageView 实例。在调用 UIView +beginAnimations 和 +commitAnimations 之间交换它们。

      【讨论】:

        【解决方案4】:

        请检查答案。我想你正在寻找这个:

        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];
        

        【讨论】:

        • 这很好用,尤其是对于推送和转换子类型。我认为这是最佳答案,因为它不需要创建任何虚假的额外视图,也不需要操纵它们的几何形状。
        【解决方案5】:

        与已解释的内容没有什么不同,但在代码中,这些是可用的转换:

        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];
        

        【讨论】:

          【解决方案6】:

          有几种方法可以做到这一点,我同意 Ben View Transitions 就是一个很好的例子。如果您正在寻找简单的全屏转换,我会考虑启动一个新的实用程序并查看 RootViewController.m 中的 toggleView 方法。尝试将UIViewAnimationTransitionFlipFromLeftUIViewAnimationTransitionFlipFromRight 切换到UIViewAnimationTransitionCurlUpUIViewAnimationTransitionCurlDown 以获得非常好的过渡效果(这只适用于设备)。

          【讨论】:

            【解决方案7】:

            这就是我所做的:褪色。 我放置了另一个具有相同 UIImage 和维度的 UIImageView,称为 tmp。 我替换了基本 UIImageView 的 UIImage。 然后我把正确的图像放在底座上(仍然被 tmp 覆盖)。

            下一步是 - 将 tmp 的 alpha 设置为零, - 根据基础的高度将基础 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];
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-03-20
              • 1970-01-01
              • 1970-01-01
              • 2016-12-15
              • 1970-01-01
              • 2010-10-21
              • 2011-04-05
              • 1970-01-01
              相关资源
              最近更新 更多