CAAnimation - изменить свойства в последнем кадре анимации? - PullRequest
1 голос
/ 01 июня 2011

Я анимирую UIView (или, скорее, его CALayer), и в конце анимации он больше не виден (я делаю 3D-преобразование, чтобы он поворачивался примерно на y на 90 °, представьте, что дверь открывается к вам)хотя он технически «виден» в том смысле, что его кадр все еще находится на экране.

В конце этой анимации я удаляю это представление из его суперпредставления в animationDidStop: finish: method.

Проблема в том, что перед кратким миганием вы видите это представление в его исходном нетрансформированном состоянии.

Мне интересно, как это исправить.Я понятия не имею.Я попытался анимировать прозрачность слоя, но это тоже не сработало.Мерцание все еще происходит.

Есть идеи?Могу ли я предоставить что-нибудь или, возможно, кто-то здесь имел эту проблему раньше?

РЕДАКТИРОВАТЬ: Вот некоторый код (прокрутите дальше вниз и найдите строку внутри if (isHalfDone) где [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;
    }

}

1 Ответ

3 голосов
/ 07 июня 2011

Это был ответ на вопрос: речь идет о свойстве animation fillMode .

...