从当前状态为UIView创建CATransition

时间:2011-08-20 15:11:47

标签: iphone ios uiview core-animation catransition

我正在尝试使用CATransition从一侧制作推送动画。我在处理两个UIViews的方法中执行此操作,一个用于背景,另一个用于前景。动画UIView是前景。但是我不希望新内容替换旧内容,所以为了做到这一点,我将所有旧内容从前台移动到后台UIView,期望它只会动画UIView的推送过渡{1}}来自一方,但它取代旧的UIView。有没有办法做我正在尝试做的事情,比如从前景和背景UIViews拥有正确内容的时刻锁定UIViews的状态?

我的代码是这样的:

UIView *newView = argView; // argView is the view passed as a parameter to the method
// move views from foreground to background
for (UIView *v in [fgView subviews]) {
    [v removeFromSuperview];
    [bgView addSubview:v];
}

// Slide animation
CATransition *transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
[fgView.layer addAnimation:transition forKey:nil];
[fgView addSubview:newView];

[edit] 我一直在做一些研究。显然(或者我认为可能发生的事情)是背景的UIViews删除采用了隐式动画。有没有办法阻止动画制作?

[edit] 答案:是的,可以完成(禁用隐式动画)并使用以下代码完成

[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
for (UIView *v in [fgView subviews]) {
    [v removeFromSuperview];
    [bgView addSubview:v];
}
[CATransaction commit];

这就是我所做的,它应该有效(根据苹果公司的开发者门户网站),但事实并非如此,所以问题仍然存在。

[edit] 经过大量的测试和阅读后,我发现问题在于,当我从超级视图中删除视图时,Transition或Animation不会识别此更改,直到后来,所以它回应了最新的变化。有没有办法强制更新或检查removeFromSuperviewaddSubview何时完成?

[edit] 我需要的是这个: 1)UIViews的当前状态是:bgView具有阴影UIView或midView后面的旧视图(此视图不应该是动画的)。一个永远不会动画的midView。一个带有当前UIView的fgView。 2)我想将fgView的内容移动到bgView(不会被动画化),并为添加到fgView的新UIView的外观设置动画(使用Slide,淡入/淡出或Flip动画)。

2 个答案:

答案 0 :(得分:5)

也许更好的方法是制作旧内容的“屏幕截图”并将屏幕截图添加为UIImageView,然后您可以将UIView的内容更改为新内容。

在此之后,您可以轻松地向两个视图添加动画,而无需担心旧内容会被更改。

您可以将以下两个文件添加到项目中,并通过调用UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithUIView:view]];获取UIView的屏幕截图

因为它是一个UIImageView,所以你不必担心视图的内容会被改变。

的UIImage + ImagewithUIView.h

@interface UIImage (UIImage+ImagewithUIView)
+ (UIImage *)imageWithUIView:(UIView *)view;
@end

的UIImage + ImagewithUIView.m

@implementation UIImage (UIImage+ImagewithUIView)
#pragma mark -
#pragma mark TakeScreenShot
static CGContextRef createBitmapContext(int pixelsWide, int pixelsHigh)
{
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = (kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGContextRef bitmapContext = CGBitmapContextCreate(nil, pixelsWide, pixelsHigh, 8, 0, colorSpace, bitmapInfo);
    CGColorSpaceRelease(colorSpace);

    return bitmapContext;
}

+ (UIImage *)imageWithUIView:(UIView *)view
{
    CGSize screenShotSize = view.bounds.size;
    CGContextRef contextRef = createBitmapContext(screenShotSize.width, screenShotSize.height);
    CGContextTranslateCTM (contextRef, 0, screenShotSize.height);
    CGContextScaleCTM(contextRef, 1, -1);

    [view.layer renderInContext:contextRef];
    CGImageRef imageRef = CGBitmapContextCreateImage(contextRef);
    CGContextRelease(contextRef);

    UIImage *img = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    // return the image
    return img;
}
@end

答案 1 :(得分:3)

UIView *newView = argView; // argView is the view passed as a parameter to the method
// move views from foreground to background
[fgView.layer removeAllAnimations]; // make sure all, if any, animations are removed.
for (UIView *v in [fgView subviews]) 
{
    // [v removeFromSuperview]; // this should not be needed addSubview does it for you
    [bgView addSubview:v];
}

// Slide animation
CATransition *transition = [CATransition animation];
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromLeft;
transition.removedOnCompletion = YES; // force removal of animation when completed.
[fgView addSubview:newView];
[fgView.layer addAnimation:transition forKey:nil];