CAAnimation - 在动画的最后一帧改变属性? [英] CAAnimation - change properties in the last frame of the animation?
问题描述
我在动画一个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屋!