【问题标题】:Flip, Grow, and Translate Animation翻转、增长和翻译动画
【发布时间】:2012-04-06 01:29:46
【问题描述】:

查看 MLB At Bat 应用程序的 this video。基本上,我只想呈现一个modalViewControllerUIModalPresentationFormSheet 样式并让它从另一个视图增长然后翻转。就像您在 MLB 应用程序的记分板上点击游戏一样。有谁知道我怎么能做到这一点?

谢谢

编辑:我的主要视图与 MLB 应用程序的设置几乎相同。我正在使用AQGridView 并希望在点击网格视图中的单元格时出现动画。

编辑 2:我也愿意放弃 UIViewController 的概念,只使用普通的 UIView,然后手动复制 UIModalPresentationFormSheet 的样式,如果这样更容易的话。

编辑 3:好的,忘记使用 UIViewController 来执行此操作,因为我没有收到任何回复,我认为这是不可能的。我的新问题是如何仅使用UIView 复制已发布视频中的动画?所以基本上,初始视图需要同时增长、移动和翻转。

编辑4:我想我已经弄清楚了实际的动画,现在我唯一的问题是计算坐标以输入CATransform3DTranslate。我的视图需要像视频中一样进行动画处理。它需要从另一个视图开始并动画到屏幕的中心。这是我尝试计算在中心弹出的视图的坐标的方法:

CGPoint detailInitialPoint = [gridView convertPoint:view.frame.origin toView:detailView.frame.origin];
CGPoint detailFinalPoint = detailView.frame.origin;

gridView 是我的主视图的容器视图,其中包含较小的网格项。 view 是我们从中制作动画的特定网格项目。 detailView 是出现在屏幕中间的视图。

【问题讨论】:

    标签: objective-c ios cocoa-touch ipad core-animation


    【解决方案1】:

    您可以使用 UIViewControler 上的类别实现自己的过渡。

    UIViewController+ShowModalFromView.h

    #import <Foundation/Foundation.h>
    #import <QuartzCore/QuartzCore.h>
    
    @interface UIViewController (ShowModalFromView)
    - (void)presentModalViewController:(UIViewController *)modalViewController fromView:(UIView *)view;
    @end
    

    UIViewController+ShowModalFromView.m

    #import "UIViewController+ShowModalFromView.h"
    
    @implementation UIViewController (ShowModalFromView)
    
    - (void)presentModalViewController:(UIViewController *)modalViewController fromView:(UIView *)view {
        modalViewController.modalPresentationStyle = UIModalPresentationFormSheet;
    
    // Add the modal viewController but don't animate it. We will handle the animation manually
    [self presentModalViewController:modalViewController animated:NO];
    
    // Remove the shadow. It causes weird artifacts while animating the view.
    CGColorRef originalShadowColor = modalViewController.view.superview.layer.shadowColor;
    modalViewController.view.superview.layer.shadowColor = [[UIColor clearColor] CGColor];
    
    // Save the original size of the viewController's view    
    CGRect originalFrame = modalViewController.view.superview.frame;
    
    // Set the frame to the one of the view we want to animate from
    modalViewController.view.superview.frame = view.frame;
    
    // Begin animation
    [UIView animateWithDuration:1.0f
                     animations:^{
                         // Set the original frame back
                         modalViewController.view.superview.frame = originalFrame;
                     }
                     completion:^(BOOL finished) {
                         // Set the original shadow color back after the animation has finished
                         modalViewController.view.superview.layer.shadowColor = originalShadowColor;
                     }];
    }
    
    @end
    

    这可以很容易地更改为使用您想要的任何动画过渡;对于您的,您可能想要使用 CA3DTransform。希望这会有所帮助!

    【讨论】:

    • 在哪里制作自定义动画?我是否将 UIView 块动画替换为 CoreAnimation 动画?
    • 是的,用更复杂的动画代替简单的 UIView 动画。不过,我不确定阴影是否会对 CoreAnimation 产生奇怪的影响。无论哪种方式都应该很容易测试。
    • 我可以让自定义动画按照你的方式工作,但我不知道如何将它与翻转结合使用这里的方法来实现翻转stackoverflow.com/a/7463047/639668
    • 您可以使用相同的方法返回 3D 变换并复制其余代码以作用于 viewController.view.layer 而不是 view2.layer。
    【解决方案2】:

    要进行翻转、增长和平移动画,您可以使用以下代码:

    - (void)animate {
        int newX, newY; //New position
        int newW, newH; //New size
        [UIView animateWithDuration:someDuration delay:someDelay animations:^{
            yourView.transform = CATransform3DMakeRotation(M_PI_2,1.0,0.0,0.0); //flip halfway
            yourView.frame = CGRectMake(newX/2, newY/2, newW/2, newH/2);
        } completion:^{
            while ([yourView.subviews count] > 0)
                [[yourView.subviews lastObject] removeFromSuperview]; // remove all subviews
            // Add your new views here 
            [UIView animateWithDuration:someDuration delay:someDelay animations:^{
                yourView.transform = CATransform3DMakeRotation(M_PI,1.0,0.0,0.0); //finish the flip
                yourView.frame = CGRectMake(newX, newY, newW, newH);
            } completion:^{
                // Flip completion code here
            }];
        }];
    }
    

    希望这会有所帮助!

    【讨论】:

    • 我希望只使用 transform 而不是 frame 来做到这一点,这样我的视图子视图就不会被扭曲。
    • 我知道如何构造变换,但我不知道如何计算图层的正确位置。
    • 我认为你可以使用CGAffineTransformConcat() 来做纯transform 就像这里stackoverflow.com/questions/1111277/… 你希望视图显示在哪里?
    • 好的,我弄清楚了动画,现在问题是计算点数。请参阅我对原始问题的第四次编辑。
    • 尝试使用 UIView 的.center 属性。也许CGPoint detailFinalPoint = CGPointMake(gridView.center.x-detailView.frame.size.width/2, gridView.center.y-detailView.frame.size.height/2);
    【解决方案3】:

    好的,我想通了。这是我所做的:

    CGFloat duration = 0.8;
    
    /*
    //Detail View Animations 
    */
    
    CATransform3D initialDetailScale = CATransform3DMakeScale(view.frame.size.width/vc.view.frame.size.width, view.frame.size.height/vc.view.frame.size.height, 1.0);
    CATransform3D initialDetailTransform = CATransform3DRotate(initialDetailScale, -M_PI, 0.0, -1.0, 0.0);
    CATransform3D finalDetailScale = CATransform3DMakeScale(1.0, 1.0, 1.0);
    CATransform3D finalDetailTransform = CATransform3DRotate(finalDetailScale, 0.0, 0.0, -1.0, 0.0);
    
    NSMutableArray *detailAnimations = [NSMutableArray array];
    
    CABasicAnimation *detailTransform = [CABasicAnimation animationWithKeyPath:@"transform"];
    detailTransform.fromValue = [NSValue valueWithCATransform3D:initialDetailTransform];
    detailTransform.toValue = [NSValue valueWithCATransform3D:finalDetailTransform];
    detailTransform.duration = duration;
    [detailAnimations addObject:detailTransform];
    
    CABasicAnimation *detailFadeIn = [CABasicAnimation animationWithKeyPath:@"opacity"];
    detailFadeIn.fromValue = [NSNumber numberWithFloat:1.0];
    detailFadeIn.toValue = [NSNumber numberWithFloat:1.0];
    detailFadeIn.duration = duration/2;
    detailFadeIn.beginTime = duration/2;
    [detailAnimations addObject:detailFadeIn];
    
    CABasicAnimation *detailMove = [CABasicAnimation animationWithKeyPath:@"position"];
    detailMove.fromValue = [NSValue valueWithCGPoint:vc.view.layer.position];
    detailMove.toValue = [NSValue valueWithCGPoint:self.view.layer.position];
    detailMove.duration = duration;
    [detailAnimations addObject:detailMove];
    
    CAAnimationGroup *detailGroup = [CAAnimationGroup animation];
    [detailGroup setAnimations:detailAnimations];
    [detailGroup setDuration:duration];
    detailGroup.removedOnCompletion = NO;
    detailGroup.fillMode = kCAFillModeForwards;
    detailGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [vc.view.layer addAnimation:detailGroup forKey:@"anim"];
    
    /*
    //Grid Item View Animations
    */
    
    CATransform3D initialGridScale = CATransform3DMakeScale(1.0, 1.0, 1.0);
    CATransform3D initialGridTransform = CATransform3DRotate(initialGridScale, 0.0, 0.0, 1.0, 0.0);
    CATransform3D finalGridScale = CATransform3DMakeScale(vc.view.frame.size.width/view.frame.size.width, vc.view.frame.size.height/view.frame.size.height, 1.0);
    CATransform3D finalGridTransform = CATransform3DRotate(finalGridScale, M_PI, 0.0, 1.0, 0.0);
    
    NSMutableArray *gridAnimations = [NSMutableArray array];
    
    CABasicAnimation *gridTransform = [CABasicAnimation animationWithKeyPath:@"transform"];
    gridTransform.fromValue = [NSValue valueWithCATransform3D:initialGridTransform];
    gridTransform.toValue = [NSValue valueWithCATransform3D:finalGridTransform];
    gridTransform.duration = duration;
    [gridAnimations addObject:gridTransform];
    
    CABasicAnimation *gridFadeOut = [CABasicAnimation animationWithKeyPath:@"opacity"];
    gridFadeOut.fromValue = [NSNumber numberWithFloat:0.0];
    gridFadeOut.toValue = [NSNumber numberWithFloat:0.0];
    gridFadeOut.duration = duration/2;
    gridFadeOut.beginTime = duration/2;
    [gridAnimations addObject:gridFadeOut];
    
    CABasicAnimation *gridMove = [CABasicAnimation animationWithKeyPath:@"position"];
    gridMove.fromValue = [NSValue valueWithCGPoint:view.layer.position];
    gridMove.toValue = [NSValue valueWithCGPoint:[self.view.layer convertPoint:self.view.layer.position toLayer:gridView.layer]];
    gridMove.duration = duration;
    [gridAnimations addObject:gridMove];
    
    CAAnimationGroup *gridGroup = [CAAnimationGroup animation];
    [gridGroup setAnimations:gridAnimations];
    gridGroup.duration = duration;
    gridGroup.fillMode = kCAFillModeForwards;
    gridGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    gridGroup.removedOnCompletion = NO;
    [view.layer addAnimation:gridGroup forKey:@"anim"];
    

    我正在处理AQGridView 中的一个项目。在我的代码示例中,view 是我正在制作动画的 AQGridViewCell 的实例。 vc.view 是我正在显示的详细信息 UIViewController/UIView

    【讨论】:

    • 我正试图让它适用于 iPhone 应用程序。在运行此代码之前,您对详细视图做了什么?您是否将详细视图控制器的视图添加到层​​次结构?如果是这样,设置了什么框架?目前,当我运行此代码时,我从网格视图中获得了半翻转,但细节视图没有出现任何内容。
    • @hundreth 我将详细视图添加为网格视图的子视图并将其居中。
    【解决方案4】:

    我强烈建议您查看this 的帖子。

    您不需要亲自处理所有这些动画。

    如果您使用UIView 类方法transitionFromView:toView:duration:options:completion: 并传入UIViewAnimationOptionTransitionFlipFromLeftUIViewAnimationOptionTransitionFlipFromRight - 无论您希望动画以哪种方式翻转。

    我已经使用这种方法实现了与 MLB 应用程序中显示的相同的东西。您的 from view 将是网格中的单元格,to view 将是单元格“背面”的内容。

    希望这会减少您需要的整体代码。

    【讨论】:

    • 我正在尝试类似的事情并苦苦挣扎。在翻转视图时,您是如何缩放视图并将其移动到位的?
    • 我已经有一段时间没有看到这个了,但我认为这将取决于您传递给 transitionFromView:toView:duration:options:completion: 方法的 fromViewtoView 视图的帧。
    【解决方案5】:

    我将使用带有自定义 UICollectionViewCell 的 UICollectionView 并使用其委托调用进行动画处理...只是其他人可以选择的示例。

    #pragma mark - UICollectionViewDelegate
    - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:  
    (NSIndexPath *)indexPath
    {
    
    
    [UIView beginAnimations:@"showImage" context:Nil];
        CGRect cellFrame = cell.frame;
        CGRect imgFram = cell.imageView.frame;
        [UIView setAnimationDuration:0.8];
        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:cell   
    cache:YES];
        cellFrame.size = CGSizeMake(200, 200);
        cellFrame.origin.y = 10;
        cellFrame.origin.x = 45;
        cell.frame = cellFrame;
        imgFram.size = CGSizeMake(200, 200);
        cell.imageView.frame = imgFram;
        [collectionView bringSubviewToFront:cell];
        [UIView commitAnimations];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-13
      • 2014-10-03
      • 2013-08-14
      • 2011-09-18
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      相关资源
      最近更新 更多