CAAnimation - 在动画的最后一帧改变属性? [英] CAAnimation - change properties in the last frame of the animation?

查看:129
本文介绍了CAAnimation - 在动画的最后一帧改变属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在动画一个UIView(或更确切地说,它的CALayer),并在动画的结尾不再是可见的(我做一个3D转换,使其旋转90°左右Y,想象一下向你开门)虽然在技术上可见的,因为它的框架仍然是在屏幕上。

目前动画的结尾,我从它的父删除的animationDidStop这一观点:完成:方法

问题是,还有就是你看到它的原始的未状态,这种观点它被删除之前短暂的闪烁。<​​/ P>

我不知道如何解决这个问题。我不知道。我试图动画图层的不透明度,但没有任何工作。闪烁仍然发生。

任何想法?我可以提供什么或者是有人在这里已经收到了这个问题?

编辑:下面是一些code(进一步向下滚动,寻找线内,如果(isHalfDone)其中[子视图removeFromSuperview];

   - (无效)pageOpenView:(UIView的*)viewToOpen时间:(NSTimeInterval)持续时间pageTurnDirection:(PageTurnDirection)p {
    //说明新的动画之前删除现有动画
    [viewToOpen.layer removeAllAnimations]    //确保视图中可见
    viewToOpen.hidden = NO;    //禁用的观点,所以它不是做anythign而动画
    viewToOpen.userInteractionEnabled = NO;    浮DIR = P == 0? -1.0F:1.0F; //为方向的计算    //创建一个动画来保存翻页
    CABasicAnimation * transformAnimation = [CABasicAnimation animationWithKeyPath:@改造];
    transformAnimation.removedOnCompletion = NO;
    transformAnimation.duration =持续时间;
    transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];    CATransform3D startTransform = CATransform3DIdentity;    如果(P == NEXT_PAGE){
        startTransform.m34 = 0.001f;
    }其他{
        startTransform.m34 = -0.001f;
    }    //从当前状态启动动画
    transformAnimation.fromValue = [NSValue valueWithCATransform3D:startTransform];
    //这是由沿Y轴90度的基本旋转
    CATransform3D endTransform = CATransform3DMakeRotation(3.141f / 2.0F,
                                                           0.0,
                                                           DIR,
                                                           0.0);
    //这些值控制3D投影前景
    如果(P == NEXT_PAGE){
        endTransform.m34 = 0.001f;
        endTransform.m14 = -0.0015f;
    }其他{
        endTransform.m34 = -0.001f;
        endTransform.m14 = 0.0015f;
    }
    transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];
    //创建一个动画组,以保存旋转
    CAAnimationGroup * theGroup = [CAAnimationGroup动画]    //设置自我为代表收到通知时,在动画完成
    theGroup.delegate =自我;
    theGroup.duration =持续时间;
    // CAAnimation对象支持任意键 - 值对,我们添加标签的UIView
    //后来查明动画,当它完成
    [theGroup的setValue:[NSNumber的numberWithInt:viewToOpen.tag] forKey:@viewToOpenTag]; //我们的标签设置页面数
    [theGroup的setValue:[NSNumber的numberWithInt:P] forKey:@PageTurnDirection];
    [theGroup的setValue:[NSNumber的numberWithBool:YES] forKey:@isAnimationMidpoint]; //即这是翻页上半年与否?    //在这里,您可以添加其他动画到数组
    theGroup.animations = [NSArray的arrayWithObjects:transformAnimation,无]
    theGroup.removedOnCompletion = NO;
    //动画组添加到层
    [viewToOpen.layer addAnimation:theGroup forKey:@flipViewOpen];
} - (无效)animationDidStop:(CAAnimation *)theAnimation完成:(BOOL)标志{
    //从动画获取标签,我们用它来查找动画的UIView
    *的NSNumber标签= [theAnimation valueForKey:@viewToOpenTag];
    PageTurnDirection DIR = [[theAnimation valueForKey:@PageTurnDirection]的intValue];
    BOOL isHalfDone = [[theAnimation valueForKey:@isAnimationMidpoint] boolValue];    UIView的* toStack; //堆栈中的页已经从
    UIView的* fromStack; //堆栈中的新页面会去。
    INT indexDirection; //将是1或-1    INT targetLastPageInStack; //想要获得加到其堆栈的页面数(即高或低)    //这取决于我们正在转向的方向,我们搜索不同的堆栈
    如果(DIR == NEXT_PAGE){
        fromStack = rightStack;
        toStack = leftStack;
        indexDirection = 1;
        INT lastPg;        UIView的* lastPgInStack;        如果([fromStack.subviews计数]&0){
            lastPgInStack = [fromStack.subviews objectAtIndex:0];            如果([lastPgInStack标签] ==的PageIndex){
                lastPg = PageIndex的; //堆栈目前最后一页的pagenr。
            }
            其他{
                //没有最后一页,所以当前页是最后一页
                lastPg = [lastPgInStack标签]
            }
        }其他{
            lastPg = PageIndex的;
        }
        targetLastPageInStack = lastPg + 2;
    }
    其他{
        fromStack = leftStack;
        toStack = rightStack;
        indexDirection = -1;
        INT lastPg;
        的UIView * lastPgInStack = [fromStack.subviews objectAtIndex:0];        如果([lastPgInStack标签] ==的PageIndex-1){
            lastPg = PageIndex的-1; //堆栈目前最后一页的pagenr。
        }
        其他{
            //没有最后一页,所以当前页是最后一页
            lastPg = [lastPgInStack标签]
        }        targetLastPageInStack = lastPg - 2;
    }
    //不同的处理,如果翻页是成功的一半,或完全完成。
    如果(isHalfDone){        UIView的子视图* = [fromStack viewWithTag:[标签的intValue];        如果(标志){
            //现在我们只是隐藏,因为动画视图
            // animation.removedOnCompletion不工作
            //动画组。隐藏视图prevents它
            //从返回到原来的状态,并示出。            subview.hidden = YES;
            [子视图removeFromSuperview] //移除动画PAGE从堆栈
            现在//该堆栈上创建一个
            如果((DIR == NEXT_PAGE&放大器;&安培; targetLastPageInStack&LT; = self.endPageIndex)||(DIR = = preV_PAGE&放大器;&安培; targetLastPageInStack&GT; = self.startPageIndex)){                BODBookPage * NEWPAGE = [BODBookPage pageInBook:放大器; myDocumentRef页次:targetLastPageInStack框架:fromStack.bounds];
                newPage.hidden = NO;
                [fromStack insertSubview:NEWPAGE atIndex:0];
            }        }        //现在创建该会翻过来,并将其添加到右侧栈页面视图。也许它设置为隐藏。
        BODBookPage * NEWPAGE = [BODBookPage pageInBook:放大器; myDocumentRef页次:[标签的intValue] + 1 * indexDirection框架:toStack.bounds];
        newPage.hidden = YES;
        [toStack addSubview:新页]
        [个体经营pageCloseView:NEWPAGE时间:turningTime / 2.0F pageTurnDirection:DIR];
    }
    其他{
        //我们只从动画片到超过翻页        //现在必须删除最遥远的观点,因此在子视图索引为0。我们这样做是认为保持内存使用率较低。
        如果([toStack.subviews计数]→1){
            [(UIView的*)[toStack.subviews objectAtIndex:0] removeFromSuperview];
        }
        的PageIndex =的PageIndex + 2 * indexDirection;
    }}


解决方案

这是问题的答案:它是关于<一个href=\"http://stackoverflow.com/questions/226555/after-animation-view-position-resets/250754#250754\">animation在fillMode属性。

I'm animating a UIView (or rather its CALayer) and at the end of the animation it is no longer visible (I do a 3D transform so that it rotates about y by 90°, imagine a door opening towards you), though it's technically 'visible' in that its frame is still on-screen.

At the end of this animation, I remove that view from its superview in the animationDidStop:finished: method.

Problem is, there's a brief flicker where you see this view in its original untransformed state before it gets removed.

I'm wondering how to fix this. I have no idea. I tried animating the layer's opacity but that didn't work either. The flicker still happens.

Any ideas? Can I provide anything or perhaps someone here has had this problem before?

EDIT: Here's some code (scroll further down and look for the line inside if(isHalfDone) where [subview removeFromSuperview];

- (void) pageOpenView:(UIView *)viewToOpen duration:(NSTimeInterval)duration pageTurnDirection:(PageTurnDirection) p{
    // Remove existing animations before stating new animation
    [viewToOpen.layer removeAllAnimations];

    // Make sure view is visible
    viewToOpen.hidden = NO;

    // disable the view so it’s not doing anythign while animating
    viewToOpen.userInteractionEnabled = NO;

    float dir = p == 0 ? -1.0f : 1.0f;  // for direction calculations

    // create an animation to hold the page turning
    CABasicAnimation *transformAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
    transformAnimation.removedOnCompletion = NO;
    transformAnimation.duration = duration;
    transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];

    CATransform3D startTransform = CATransform3DIdentity;

    if (p == NEXT_PAGE) {
        startTransform.m34 = 0.001f;
    }else {
        startTransform.m34 = -0.001f;
    }

    // start the animation from the current state
    transformAnimation.fromValue = [NSValue valueWithCATransform3D:startTransform];
    // this is the basic rotation by 90 degree along the y-axis
    CATransform3D endTransform = CATransform3DMakeRotation(3.141f/2.0f,
                                                           0.0f,
                                                           dir,
                                                           0.0f);
    // these values control the 3D projection outlook
    if (p == NEXT_PAGE) {
        endTransform.m34 = 0.001f;
        endTransform.m14 = -0.0015f;
    }else {
        endTransform.m34 = -0.001f;  
        endTransform.m14 = 0.0015f;
    }


    transformAnimation.toValue = [NSValue valueWithCATransform3D:endTransform];


    // Create an animation group to hold the rotation
    CAAnimationGroup *theGroup = [CAAnimationGroup animation];

    // Set self as the delegate to receive notification when the animation finishes
    theGroup.delegate = self;
    theGroup.duration = duration;
    // CAAnimation-objects support arbitrary Key-Value pairs, we add the UIView tag
    // to identify the animation later when it finishes
    [theGroup setValue:[NSNumber numberWithInt:viewToOpen.tag] forKey:@"viewToOpenTag"];  // We set the tag to the page number
    [theGroup setValue:[NSNumber numberWithInt: p] forKey:@"PageTurnDirection"]; 
    [theGroup setValue:[NSNumber numberWithBool:YES] forKey:@"isAnimationMidpoint"];  // i.e. is this the first half of page-turning or not?

    // Here you could add other animations to the array
    theGroup.animations = [NSArray arrayWithObjects:transformAnimation,  nil];
    theGroup.removedOnCompletion = NO;
    // Add the animation group to the layer
    [viewToOpen.layer addAnimation:theGroup forKey:@"flipViewOpen"];
}

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
    // Get the tag from the animation, we use it to find the animated UIView
    NSNumber *tag = [theAnimation valueForKey:@"viewToOpenTag"];  
    PageTurnDirection dir = [[theAnimation valueForKey:@"PageTurnDirection"] intValue];  
    BOOL isHalfDone = [[theAnimation valueForKey:@"isAnimationMidpoint"] boolValue];

    UIView *toStack;    // the stack the page has moved from
    UIView *fromStack;  // the stack the new page will go to.
    int indexDirection;  // will be either 1 or -1

    int targetLastPageInStack;  // the page number that wants to get added to its stack  (i.e. either high or low)

    // depending on which direction we are turning, we search a different stack
    if (dir == NEXT_PAGE) {
        fromStack = rightStack;
        toStack = leftStack;
        indexDirection = 1;
        int lastPg;

        UIView *lastPgInStack;

        if ([fromStack.subviews count] > 0) {
            lastPgInStack = [fromStack.subviews objectAtIndex:0];

            if ([lastPgInStack tag] == pageIndex) {
                lastPg = pageIndex;  // pagenr of currently last page in stack.
            }
            else {
                // there was no last page, so the current page is the last page
                lastPg = [lastPgInStack tag];
            }
        }else {
            lastPg = pageIndex;
        }


        targetLastPageInStack = lastPg + 2;
    }
    else {
        fromStack = leftStack;
        toStack = rightStack;
        indexDirection = -1;
        int lastPg;
        UIView *lastPgInStack = [fromStack.subviews objectAtIndex:0];

        if ([lastPgInStack tag] == pageIndex-1) {
            lastPg = pageIndex-1;  // pagenr of currently last page in stack.
        }
        else {
            // there was no last page, so the current page is the last page
            lastPg = [lastPgInStack tag];
        }

        targetLastPageInStack = lastPg - 2;
    }


    // different handling if the page turning is half done, or fully done.
    if (isHalfDone) {

        UIView *subview = [fromStack viewWithTag:[tag intValue]];

        if (flag) {
            // Now we just hide the animated view since
            // animation.removedOnCompletion is not working
            // in animation groups. Hiding the view prevents it
            // from returning to the original state and showing.

            subview.hidden = YES;
            [subview removeFromSuperview];  // REMOVE THE ANIMATED PAGE FROM THE STACK


            // now create one on that stack
            if ((dir == NEXT_PAGE && targetLastPageInStack <= self.endPageIndex) || (dir == PREV_PAGE && targetLastPageInStack >= self.startPageIndex)) {

                BODBookPage *newPage = [BODBookPage pageInBook:&myDocumentRef pageNum:targetLastPageInStack frame:fromStack.bounds] ;
                newPage.hidden = NO;
                [fromStack insertSubview:newPage atIndex:0];
            }

        }

        // now create the view for the page that'll be turned over and add it to the right stack.  Probably set it to hidden as well.
        BODBookPage *newPage = [BODBookPage pageInBook:&myDocumentRef pageNum:[tag intValue] + 1*indexDirection frame:toStack.bounds] ;
        newPage.hidden = YES;
        [toStack addSubview:newPage];
        [self pageCloseView:newPage duration:turningTime/2.0f pageTurnDirection:dir];
    }
    else {
        // we just animated the page turning from up to over

        // now have to remove the most distant view, so the view at subview index 0.  We do this to keep memory usage low.
        if ([toStack.subviews count] > 1) {
            [(UIView*)[toStack.subviews objectAtIndex:0] removeFromSuperview];
        }


        pageIndex = pageIndex + 2*indexDirection;
    }

}

解决方案

This was the answer to the question: it's about the animation fillMode property.

这篇关于CAAnimation - 在动画的最后一帧改变属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆