iOS7 自定义视图切换动画

19、iOS 动画开发:UIPercentDrivenInteractiveTransition 与 UIViewPropertyAnimator 实战 本文深入讲解了 iOS 动画开发中两个重要的工具:UIPercentDrivenInteractiveTransition 和 UIViewPropertyAnimator。通过实战示例,介绍了如何使用 UIPercentDrivenInteractiveTransition 实现交互式过渡动画,并结合手势识别(如 UIPanGestureRecognizer)实现动态过渡效果;同时详细展示了 UIViewPropertyAnimator 的使用方法,包括基础动画、关键帧动画、动画状态管理及性能优化技巧。文 阅读详情
 在iOS7以前,开发者如果希望定制导航控制器推入推出视图时的转场动画,一般都只能通过子类化UINavigationController或者自己编写动画代码去覆盖相应的方法,现在iOS7为开发者带来了福音,苹果公司引入了大量新API,给予了开发者很高的自由度,在处理由UIViewController管理的UIView动画时,这些API使用方便,可扩展性也很强,定制起来非常轻松:
 
• 全新的针对UIView的动画block方法
• 全新的UIViewControllerAnimatedTransitioning协议以及动画控制器的概念
• Interaction Controllers以及Transition Coordinators
• 全新的针对动画的助手API(简便方法)
 
这里我编写了一个示例应用程序,其中展示了我将在这篇文章中所提到的一些技巧, 为了快速理解我们应当如何使用iOS7的新API来处理
UIViewController的转场动画,请在此链接中下载该示例。
/cms/uploads/soft/131224/4673-131224114628.zip
 
全新的针对UIView的动画block方法
iOS4的发布带来了强大的block方法,在编写UIView动画时使用block可以轻松地得到满意的效果,然而有些情况下,我们还是不得不直接使用Core Animation。幸运的是,苹果公司在iOS7中增加了2个新的基于block的方法,这样我们就很少再需要直接使用Core Animation了。
 
关键帧动画
iOS7为UIView封装了一组API,让我们很容易的得到与Core Animation框架中的CAKeyframeAnimation一样的效果。
 
 
  1. [UIView animateKeyframesWithDuration:duration delay:delay 
  2. options:options animations:^{ 
  3. [UIView addKeyframeWithRelativeStartTime:0.0 
  4. relativeDuration:0.5 animations:^{ 
  5. //第一帧要执行的动画 
  6. }]; 
  7. [UIView addKeyframeWithRelativeStartTime:0.5 
  8. relativeDuration:0.5 animations:^{ 
  9. //第二帧要执行的动画 
  10. }]; 
  11. } completion:^(BOOL finished) { 
  12. //动画结束后执行的代码块 
  13. }]; 
新引入的animateKeyframesWithDuration与CAKeyframeAnimation的关系,可以比对animateWithDuration和CABasicAnimation,我们只需要将每一帧动画加入到block方法中,并传入此段动画在全过程中的相对开始时间和执行时间(duration具体是指此段动画的执行时间占全过程的百分比)。同时,你可以在一次动画中使用多个关键帧,只需使用addKeyframe依次将所有关键帧加入动画执行栈中。
 
下面是一个简单的例子:在示例应用中,我使用关键帧block来退出模态视图控制器。
 
 
  1. [UIView addKeyframeWithRelativeStartTime:0.0 
  2. relativeDuration:0.15 animations:^{ 
  3. //顺时针旋转90度 
  4. snapshot.transform = CGAffineTransformMakeRotation(M_PI * 
  5. -1.5); 
  6. }]; 
  7. [UIView addKeyframeWithRelativeStartTime:0.15 
  8. relativeDuration:0.10 animations:^{ 
  9. //180度 
  10. snapshot.transform = CGAffineTransformMakeRotation(M_PI * 
  11. 1.0); 
  12. }]; 
  13. [UIView addKeyframeWithRelativeStartTime:0.25 
  14. relativeDuration:0.20 animations:^{ 
  15. //摆过中点,225度 
  16. snapshot.transform = CGAffineTransformMakeRotation(M_PI * 
  17. 1.3); 
  18. }]; 
  19. [UIView addKeyframeWithRelativeStartTime:0.45 
  20. relativeDuration:0.20 animations:^{ 
  21. //再摆回来,140度 
  22. snapshot.transform = CGAffineTransformMakeRotation(M_PI * 
  23. 0.8); 
  24. }]; 
  25. [UIView addKeyframeWithRelativeStartTime:0.65 
  26. relativeDuration:0.35 animations:^{ 
  27. //旋转后掉落 
  28. //最后一步,视图淡出并消失 
  29. CGAffineTransform shift = 
  30. CGAffineTransformMakeTranslation(180.0, 0.0); 
  31. CGAffineTransform rotate = 
  32. CGAffineTransformMakeRotation(M_PI * 0.3); 
  33. snapshot.transform = CGAffineTransformConcat(shift, 
  34. rotate); 
  35. _coverView.alpha = 0.0; 
  36. }]; 
视图仿佛在重力的牵引下绕左下角顺时针旋转,并在最低点摆动了一下,最后脱落。
 
弹簧动画
iOS7新引入的另一个block方法可以让你轻松将真实物理世界中的弹性效果集成进视图动画中。苹果公司一直建议开发者尽可能将动画效果做的跟真实物理世界一样——在视图滑动时,可以像弹簧一样,稍微拉伸一些,再弹回正确位置。使用新的弹簧动画API来实现此效果相较以往要简单很多。
 
 
  1. [UIView animateWithDuration:duration delay:delay 
  2. usingSpringWithDamping:damping initialSpringVelocity:velocity 
  3. options:options animations:^{ 
  4. //这里书写动画相关代码 
  5. } completion:^(BOOL finished) { 
  6. //动画结束后执行的代码块 
  7. }]; 
 
这里用到了一些物理上的概念:damping参数代表弹性阻尼,随着阻尼值越来越接近0.0,动画的弹性效果会越来越明显,而如果设置阻尼值为1.0,则视图动画不会有弹性效果——视图滑动时会直接减速到0并立刻停止,不会有弹簧类的拉伸效果。
 
velocity参数代表弹性修正速度,它表示视图在弹跳时恢复原位的速度,例如,如果在动画中视图被拉伸的最大距离是200像素,你想让视图以100像素每秒的速度恢复原位,那么就设置velocity的值为0.5。(译者:建议大家看看源代码,代码中damping设置为0.8不够明显,你可以将damping调为0.1,然后慢慢调整velocity看看效果)
 
在示例应用程序中,我用弹簧动画让模态视图控制器从屏幕底部滑上来,设置弹性阻尼为0.8,弹性修正速度为1.0,运行后可以看到,视图将冲出15像素的距离,然后慢慢降回原位。如果我设置弹性阻尼为0.6或者更小,那么视图会冲得更高,而且降回原位前还会继续向下反弹。(也就是停止前来回弹的次数越来越多,弹性效果越来越明显)需要注意的是,不要将弹性动画与UIKit的动态特效引擎相混淆。弹性动画是一个标准的UIView动画API,仅仅提供了有限的几种真实物理效果。
 
自定义UIViewController的转场动画
现在让我们来看一个好东西。苹果公司不仅为开发者引入了新的动画API,而且还扩大了其应用范围。在使用UIViewController管理视图的推入推出时,可以很容易地自定义以下转场动画:
• UIViewController
• presentViewController
• UITabBarController
• setSelectedViewController
• setSelectedIndex
• UINavigationController
• pushViewController
• popViewController
• setViewControllers
 
在示例应用程序中,我创建了一系列转场动画,在动画中使用了之前讲解过的新引入的弹簧动画和关键帧block方法,现在让我们来看看如何使用新API来自定义上述的转场动画。
 
核心概念:动画控制器
那么,如何在使用自定义动画的同时不影响视图的其他属性?对此苹果公司提供了一个新的协议:UIViewControllerAnimatedTransitioning,我们可以在协议方法中编写自定义的动画代码。苹果开发者文档中称实现了此协议的对象为动画控制器。
 
由于我们使用了协议这一语法特性,自定义动画的代码可以灵活的放在自己想要的位置。你可以创建一个专门用于管理动画的类, 也可以让UIViewController实现UIViewControllerAnimatedTransitioning接口。由于需要实现一系列不同的动画,因此选择为每个动画创建一个类。接下来创建这些动画类的通用父类——BaseAnimation,它定义了一些通用的属性和助手方法。
 
让我们来看第一个动画,使用UINavigationController推入推出视图时,会有一个简单的缩放效果。
 
 
  1. -(void)animateTransition: 
  2. (id<UIViewControllerContextTransitioning>)transitionContext { 
  3. //获取容器视图引用 
  4. UIView *containerView = [transitionContext 
  5. containerView]; 
  6. UIViewController *fromViewController = [transitionContext 
  7. viewControllerForKey:UITransitionContextFromViewControllerKey 
  8. ]; 
  9. UIViewController *toViewController = [transitionContext 
  10. viewControllerForKey:UITransitionContextToViewControllerKey]; 
  11. if (self.type == AnimationTypePresent) { 
  12. //插入“to”视图,初始缩放值为0.0 
  13. toViewController.view.transform = 
  14. CGAffineTransformMakeScale(0.0, 0.0); 
  15. [containerView insertSubview:toViewController.view 
  16. aboveSubview:fromViewController.view]; 
  17. //缩放“to”视图为想要的效果 
  18. [UIView animateWithDuration:[self 
  19. transitionDuration:transitionContext] animations:^{ 
  20. toViewController.view.transform = 
  21. CGAffineTransformMakeScale(1.0, 1.0); 
  22. } completion:^(BOOL finished) { 
  23. [transitionContext completeTransition:YES]; 
  24. }]; 
  25. } else if (self.type == AnimationTypeDismiss) { 
  26. //插入“to”视图 
  27. [containerView insertSubview:toViewController.view 
  28. belowSubview:fromViewController.view]; 
  29. //缩小“from”视图,直到其消失 
  30. [UIView animateWithDuration:[self 
  31. transitionDuration:transitionContext] animations:^{ 
  32. fromViewController.view.transform = 
  33. CGAffineTransformMakeScale(0.0, 0.0); 
  34. } completion:^(BOOL finished) { 
  35. [transitionContext completeTransition:YES]; 
  36. }]; 
  37. } 
  38. } 
  39. -(NSTimeInterval)transitionDuration: 
  40. (id<UIViewControllerContextTransitioning>)transitionContext { 
  41. return 0.4; 
  42. } 
符合UIViewControllerAnimatedTransitioning协议的任何对象都需要实现animateTransition:和transitionDuration:两个方法。你也可以选择实现@optional方法animationEnded:,它在动画完成后由系统自动调用,相当于completion block,非常方便。
 
在animateTransition:中你需要处理以下过程:
1. 将“to”视图插入容器视图
2. 将“to”和“from”视图分别移动到自己想要的位置
3. 最后,在动画完成时千万别忘了调用completeTransition: 方法
UIViewControllerAnimatedTransitioning协议中的方法都带有一个参数:transitionContext,这是一个系统级的对象,它符合 UIView-ControllerContextTransitioning协议,我们可以从该对象中获取用于控制转场动画的必要信息,主要包括以下内容:
 
 
显然,苹果公司帮助开发者完成了大部分让人讨厌的细节工作,仅仅需要我们自己完成的工作就是定义动画的初始状态和终止状态,并调整到自己满意的效果。最后我再啰嗦两句有关transitionContext的重要注意事项:
 
1.获取frame的方法可能会返回CGRectZero——如果系统无法确定该frame的值具体是什么。例如,如果你使用自定义的模态视图控制器
推出动画,在结束时系统无法确定其finalFrame。
2.如果视图控制器已经从屏幕上移除了,那么获取frame的方法也会返回CGRectZero。例如在导航控制器的转场动画结束后,试图获取“from”视图的finalFrame。
你不用手动去移除“from”视图,transitionContext将自动帮你完成。
3.如果你在应用的其他地方需要使用transitionContext,你可以放心地使用动画控制器保留一个transitionContext的引用。
将动画控制器应用到转场动画中。
 
现在,我们已经开发好了动画控制器,那么最后需要做的就是,将它们应用到转场动画中:我们需要对管理转场动画的UIViewController做一些操作。
 
一般来说,我们只需要让UIViewController符合UIViewController-TransitioningDelegate 协议, 编写animationController-ForPresentedController和animationControllerForDismissedController方法。在我的示例应用程序中,我设置了一个属性,用来让动画控制器知道目前正在推入还是推出视图:
 
 
  1. -(id<UIViewControllerAnimatedTransitioning>) 
  2. animationControllerForPresentedController:(UIViewController 
  3. *)presented presentingController:(UIViewController 
  4. *)presenting sourceController:(UIViewController *)source { 
  5. modalAnimationController.type = AnimationTypePresent; 
  6. return modalAnimationController; 
  7. } 
  8. -(id<UIViewControllerAnimatedTransitioning>) 
  9. animationControllerForDismissedController:(UIViewController 
  10. *)dismissed { 
  11. modalAnimationController.type = AnimationTypeDismiss; 
  12. return modalAnimationController; 
  13. } 
 
然后,在推入模态视图控制器时,我们设置modalPresentationStyle为UIModalPresentationFullScreen或UIModalPresentationCustom。我们还必须将一个符合UIViewControllerTransitioningDelegate协议的对象设置为它的transitioningDelegate,一般来说都是推入该模态视图控制器的UIViewController。
 
 
  1. OptionsViewController *modal = [[OptionsViewController alloc] 
  2. initWithNibName:@"OptionsViewController" bundle:[NSBundle 
  3. mainBundle]]; 
  4. modal.transitioningDelegate = self; 
  5. modal.modalPresentationStyle = UIModalPresentationCustom; 
  6. [self presentViewController:modal animated:YES 
  7. completion:nil]; 
如果需要将动画控制器应用到UINavigationController的转场动画中,我们需要使用UINavigationControllerDelegate协议中的一个新方法:animationControllerForOperation。对于任何自定义的导航转场动画,导航栏都会有一个淡入淡出的动画过程。同样,对于UITabBarController,使用UITabBarControllerDelegate协议的新方法——animationController-ForTransitionFromViewController。
 
为转场动画定义交互方式
在iOS7中,苹果到处都在使用交互式弹出手势,同时,苹果也给开发者们提供了一系列工具,只需简单几步就能将交互手势应用在视图切换过程中。我们可以通过相应的委托方法返回一个交互控制器:
• UINavigationController
• interactionControllerForAnimationController
• UITabBarController
• interactionControllerForAnimationController
• UIViewController
• interactionControllerForPresentation
• interactionControllerForDismissal
 
这里唯一需要注意的是,如果没有自定义转场动画,这些方法就不会起作用。例如,你必须从animationControllerForOperation得到一个有效的动画控制器,UINavigationController才会调用interactionController-
ForAnimationController——即使你在转场交互中没有使用动画控制器。
 
其次,交互控制器非常灵活,有很强的可扩展性。虽然在示例应用程序中我使用手势检测来控制交互,但是你也可以用手势以外的其他方式来实现。你可以设计任意你想要的效果用以转场交互。
 
交互控制器:最简单的实现方式有两种方式可以创建交互控制器。第一个也是最简单的一个,就是使用UIPercentDrivenInteractiveTransition。
 
 
  1. @interface UIPercentDrivenInteractiveTransition : NSObject 
  2. <UIViewControllerInteractiveTransitioning> 
  3. @property (readonly) CGFloat duration; 
  4. @property (readonly) CGFloat percentComplete; 
  5. @property (nonatomic,assign) CGFloat completionSpeed; 
  6. @property (nonatomic,assign) UIViewAnimationCurve 
  7. completionCurve; 
  8. - (void)updateInteractiveTransition:(CGFloat)percentComplete; 
  9. - (void)cancelInteractiveTransition; 
  10. - (void)finishInteractiveTransition; 
这个类具体实现了UIViewControllerInteractiveTransitioning协议,我们可以使用它轻松为动画控制器添加自定义的交互方式。只要为目标视图加入手势(或者其他交互方式)并调用updateInteractiveTransition:,传入动画时间占整个过程的百分比即可。同时, 记住在交互完成后调用finishInteractiveTransition: , 交互被取消时调用cancel-InteractiveTransition:。下面的例子展示了如何将捏合手势应用到转场动画中:
 
 
  1. -(void)handlePinch:(UIPinchGestureRecognizer *)pinch { 
  2. CGFloat scale = pinch.scale; 
  3. switch (pinch.state) { 
  4. case UIGestureRecognizerStateBegan: { 
  5. _startScale = scale; 
  6. self.interactive = YES; 
  7. [self.navigationController 
  8. popViewControllerAnimated:YES]; 
  9. break; 
  10. } 
  11. case UIGestureRecognizerStateChanged: { 
  12. CGFloat percent = (1.0 - scale/_startScale); 
  13. [self updateInteractiveTransition:(percent < 0.0) ? 
  14. 0.0 : percent]; 
  15. break; 
  16. } 
  17. case UIGestureRecognizerStateEnded: { 
  18. CGFloat percent = (1.0 - scale/_startScale); 
  19. BOOL cancelled = ([pinch velocity] < 5.0 && percent 
  20. <= 0.3); 
  21. if (cancelled) [self cancelInteractiveTransition]; 
  22. else [self finishInteractiveTransition]; 
  23. break; 
  24. } 
  25. case UIGestureRecognizerStateCancelled: { 
  26. CGFloat percent = (1.0 - scale/_startScale); 
  27. BOOL cancelled = ([pinch velocity] < 5.0 && percent 
  28. <= 0.3); 
  29. if (cancelled) [self cancelInteractiveTransition]; 
  30. else [self finishInteractiveTransition]; 
  31. break; 
  32. } 
  33. } 
  34. } 
当你继承了UIPercentDrivenInteractiveTransition类,交互过程中系统会自动调用动画控制器的animateTransition:方法,按照你传递的percentComplete参数实时地展现动画效果。在交互完成后,它还自动调用animateTransition:方法恢复到正常状态,一旦交互完成,我们就可以改变completionSpeed和completionCurve属性来修改其他的一些样式。
 
交互控制器:通过自定义的方式
如果你需要深入控制UIPercentDrivenInteractiveTransition处理转场动画的细节,那么就不用去继承该类,而是使用UIViewController-InteractiveTransitioning协议。此协议与UIViewController-AnimatedTransitioning类似,我们可以通过该协议控制所有关于转场动画的细节。在该协议中我们需要完成以下步骤:
 
1. 实现startInteractiveTransition:方法,用于初始化专场动画。
2. 获取transitionContext 对象的引用(如果继承了UIPercentDrivenInteractiveTransition,可以看到它自动帮我们完成了这一步骤,因此这里我们必须手动获取该对象)。
3. 和之前一样,在适当的情况下调用updateInteractiveTransition:,cancelInteractiveTransition和finishInteractiveTransition(对于导航控制器来说,完成方法中还需要显示或隐藏导航栏)。
4. 完成后仍然请记住调用transitionCompleted:。
 
下面是我通过自定义的交互控制器来实现与之前相同的动画,仍然是使用捏合手势控制转场动画。
 
 
  1. -(void)startInteractiveTransition: 
  2. (id<UIViewControllerContextTransitioning>)transitionContext { 
  3. //获取transitionContext对象的引用 
  4. _context = transitionContext; 
  5. //获取容器视图引用 
  6. UIView *containerView = [transitionContext 
  7. containerView]; 
  8. UIViewController *fromViewController = [transitionContext 
  9. viewControllerForKey:UITransitionContextFromViewControllerKey 
  10. ]; 
  11. UIViewController *toViewController = [transitionContext 
  12. viewControllerForKey:UITransitionContextToViewControllerKey]; 
  13. //插入“to”视图 
  14. toViewController.view.frame = [transitionContext 
  15. finalFrameForViewController:toViewController]; 
  16. [containerView insertSubview:toViewController.view 
  17. belowSubview:fromViewController.view]; 
  18. //保留需要缩?小的视图的引用 
  19. _transitioningView = fromViewController.view; 
  20. } 
  21. -(void)updateWithPercent:(CGFloat)percent { 
  22. CGFloat scale = fabsf(percent-1.0); 
  23. _transitioningView.transform = 
  24. CGAffineTransformMakeScale(scale, scale); 
  25. [_context updateInteractiveTransition:percent]; 
  26. } 
  27. -(void)end:(BOOL)cancelled { 
  28. if (cancelled) { 
  29. [UIView animateWithDuration:_completionSpeed 
  30. animations:^{ 
  31. _transitioningView.transform = 
  32. CGAffineTransformMakeScale(1.0, 1.0); 
  33. } completion:^(BOOL finished) { 
  34. [_context cancelInteractiveTransition]; 
  35. [_context completeTransition:NO]; 
  36. }]; 
  37. } else { 
  38. [UIView animateWithDuration:_completionSpeed 
  39. animations:^{ 
  40. _transitioningView.transform = 
  41. CGAffineTransformMakeScale(0.0, 0.0); 
  42. } completion:^(BOOL finished) { 
  43. [_context finishInteractiveTransition]; 
  44. [_context completeTransition:YES]; 
  45. }]; 
  46. } 
  47. } 
你可以让动画控制器同时实现UIViewControllerInteractive-Transitioning和 UIViewControllerAnimatedTransitioning(像示例程序中那样),从而把所有代码都放在一个类中。你也可以将交互控制器和动画控制器分成两个类——协议这一语法特性的妙处在于,你可以轻松实现符合需求的最佳解决方案。
 
更多小技巧
在block中选择是否进行动画
开发者或许会遇到这样一种情况:在一串精美的动画效果中,我们需要让某些视图不进行动画,从而营造一种动静相宜的效果。在动画block方法推出之前,我们可以在[UIView beginAnimations]和[UIView commitAnimations]之间使用setAnimationsEnabled方法来设置哪些动画不需要执行。而在iOS7SDK中,苹果公司为开发者提供了新方法,只要把不需要执行的动画写在block中即可:
 
 
  1. [UIView performWithoutAnimation:^{ 
  2. //确保不执行动画 
  3. }]; 
你可以随时执行这段代码来控制不需要执行的动画。
 
集合视图的导航转场动画
你可能对UICollectionView的setLayout:animated:方法非常熟悉了。在iOS7中,当导航控制器推入推出集合视图控制器时,如果开启了 useLayout-ToLayoutNavigationTransitions属性,系统将自动调用setLayout:animated:方法。因此,在你推入集合视图控制器时,只需要设置该属性,导航控制器就可以自动执行动画,和你手动对集合视图调用setLayout:animated方法的效果一样。
 
 
  1. CollectionViewController *VC = [[CollectionViewController 
  2. alloc] initWithCollectionViewLayout:flowLayout]; 
  3. VC.title = @"Mini Apples"; 
  4. VC.useLayoutToLayoutNavigationTransitions = YES; 
  5. [self.navigationController pushViewController:VC 
  6. animated:YES]; 
转场动画调度器
还有一个非常有用的API, 它可以帮助视图控制器管理转场动画:UIViewControllerTransitionCoordinator协议。在iOS7中,每一个视图控制器(当然也包括UINavigationController和UITabBarController)都有一个transitionCoordinator属性,该属性提供了一系列用于转场动画的强大工具,首先我们来看看animateAlongsideTransition:方法。
 
 
  1. [self.transitionCoordinator 
  2. animateAlongsideTransition:^(id<UIViewControllerTransitionCoo 
  3. rdinatorContext> context) { 
  4. //要执行的动画 
  5. } 
  6. completion:^(id<UIViewControllerTransitionCoordinatorContext> 
  7. context) { 
  8. //动画结束后执行的代码块 
  9. }]; 
我们可以通过这个方法在进行转场动画时并行执行一些其他动画,context参数和之前提到的符合UIViewControllerContextTransitioning协议的transitionContext参数相类似,从该参数中我们可以获取有关转场过程的一些重要信息,包括container view和转场效果。苹果公司甚至允许开发者不传入context参数,只传入完成后执行的block。所以请大胆尝试使用它吧。
 
对于交互转场来说, 视图在转场过程中状态可能发生改变, 于是notifyWhenInteractionEndsUsingBlock:方法特别有用——它可以用来管理视图状态。在交互转场中,viewWillAppear:方法或许会在某个视图控制器推入时被调用,但是按照常理随后应该会被调用的viewDidAppear:则不一定,因为用户随时可能取消该交互(例如在之前的例子中,捏到一半又恢复原状)。
 
由此,如果我们不希望在这种情况下修改视图状态,我们可以使用该方法,恢复对视图的更改(使用UIViewControllerTransitionCoordinatorContext的isCancelled属性)。
 
 
  1. [self.transitionCoordinator 
  2. notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTran 
  3. sitionCoordinatorContext> context) { 
  4. //动画结束后执?行的代码块 
  5. }]; 
 
屏幕快照
在iOS7 以前, 获取一个UIView的快照有以下步骤: 首先创建一个UIGraphics的图像上下文,然后将视图的layer渲染到该上下文中,从而取得一个图像,最后关闭图像上下文,并将图像显示在UIImageView中。现在我们只需要一行代码就可以完成上述步骤了:
 
 
  1. [view snapshotViewAfterScreenUpdates:NO]; 
这个方法制作了一个UIView的副本,如果我们希望视图在执行动画之前保存现在的外观,以备之后使用(动画中视图可能会被子视图遮盖或者发生其他一些变化),该方法就特别方便。
 
afterUpdates参数表示是否在所有效果应用在视图上了以后再获取快照。例如,如果该参数为NO,则立马获取该视图现在状态的快照,反之,以下代码只能得到一个空白快照:
 
 
  1. [view snapshotViewAfterScreenUpdates:YES]; 
  2. [view setAlpha:0.0]; 
由于我们设置afterUpdates参数为YES,而视图的透明度值被设置成了0,所以方法将在该设置应用在视图上了之后才进行快照,于是乎屏幕空空如也。另外就是……你可以对快照再进行快照……继续快照……
 
结论
苹果公司在iOS7中为开发者添加了新的用于创建和自定义动画的API。iOS7 SDK不仅引入了强大的动画block和许多易于使用的方法,而且彻底改变了为视图自定义动画的方式。最后,强烈建议你将示例应用程序的代码下载下来,看看我在本文中介绍的API的使用方法!
 
Objective-C动画学习之自定义动画切换的相关的主要API VC容器的主要目的是解决将不同VC添加到同一个屏幕上的需求,以及可以提供一些简单的自定义切换效果。使用VC容器可以使view的关系正确,使添加的VC能够正确接收到例如屏幕旋转,viewDidLoad:等VC事件,进而进行正确相应。VC容器确实可以解决一部分问题,但是也应该看到,对于自定义切换效果来说,这样的解决还有很多不足。首先是代码高度耦合,VC切换部分的代码直接写在container中,难以分离 阅读详情

相关推荐

iOS 自定义页面的切换动画与交互动画

在iOS7之前,开发者为了寻求自定义Navigation Controller的Push/Pop动画,只能受限于子类化一个UINavigationController,或是用自定义的动画去覆盖它。但是随着iOS7的到来,Apple针对开发者推出了新的工具,以更灵活地方式管理UIViewController切换。

iOS7教程系列:自定义导航转场动画以及更多

转自cocoachina:http://www.cocoachina.com/gamedev/misc/2013/1224/7597.html 原文:iOS 7 Tutorial Series: Custom Navigation Transitions & More 感谢翻译小组成员dingdaojun热心翻译。本篇文章是我们每周推荐优秀国外的技术类文章的

^遗失 1221

Qt实战:用QCustomPlot实现毫秒级时间轴数据动态刷新(附完整代码)

本文深入探讨了在Qt框架下,如何利用QCustomPlot库高效实现毫秒级时间轴数据的动态刷新与实时可视化。针对工业物联网等高频数据场景,文章提供了从原理剖析、核心代码实现到性能优化的完整实战指南,包括滑动窗口管理、双定时器策略及坐标轴精确配置,帮助开发者构建稳定、流畅的专业级监控界面。

qsc90123456的博客 759

ViewController Transition——Modally交互动画

Modally交互动画

weixin_46908889的博客 576

边缘智能新篇章:RK3588上YOLOv8姿态估计的轻量化部署与性能优化实战

本文详细介绍了在RK3588平台上部署和优化YOLOv8姿态估计模型的完整流程。通过模型转换、ONNX中间表示和性能优化策略,实现在边缘设备上的高效实时推理,为嵌入式AI应用提供可行的轻量化解决方案。

ik6789012的博客 151

远程桌面连接失败?手把手教你解决CredSSP加密Oracle漏洞(Win10/Win11通用)

本文详细解析了Windows远程桌面连接因CredSSP加密Oracle漏洞安全更新导致的“身份验证错误”问题。文章从原理入手,提供了通过组策略编辑器(适用于专业版)和注册表编辑器(适用于家庭版)两种核心解决方案,指导用户将安全策略调整为推荐的“缓解”模式,以在保障安全的前提下恢复连接,并给出了高级脚本处理与安全最佳实践。

u6v7w8x的博客 728

AWPercentDrivenInteractiveTransition:自定义视图控制器交互式转场的完美解决方案

AWPercentDrivenInteractiveTransition:自定义视图控制器交互式转场的完美解决方案 项目介绍 AWPercentDrivenInteractiveTransition 是一个用于自定义容器视图控制器的 UIPercentDrivenInteractiveTransition 替代品。苹果原生的 UIPercentDrivenInteractiveTransition...

gitblog_00047的博客 388

RK3588部署Zipformer模型问题总结

本文分享了在RK3588嵌入式设备上部署小米Zipformer语音识别模型时遇到的问题及解决方法。主要遇到两个问题:1)在rknn_model_zoo例程编译时出现静态库版本不兼容,通过重新编译kaldi-native-fbank库并修改链接路径解决;2)sherpa-onnx编译时提示缺少portaudio库,通过修改编译脚本启用相关宏定义后成功编译。最终成功在RK3588上运行Zipformer模型,测试结果显示该模型具有较好的识别效果和实时性(RTF=0.22),验证了其在边缘设备上的适用性。

pkyang2004的博客 2148

iOS7入门介绍

本文介绍iOS7中新引入的主要API,包括视图控制器的切换,UIView动画强化,UIKit动力学和Text Kit,同时它也介绍了用户界面的变化和多任务处理能力的增强。   概述          iOS7对iOS系列来说是一个重要的更新。它引入了一个全新的用户界面设计,这个设计把重点放在内容上,而不是应用。除了视觉上的改变,iOS7增加了许多新的API来创建更丰富的用户交互和体验。本文档

Xamarin移动跨平台解决方案,用C#轻松开发iOS、Android应用 4745

Python爬虫实战:逆向解析央视频加密参数(附完整代码)

本文详细解析了央视频加密体系的技术实现,通过Python逆向工程实战演示如何解密动态密钥、AES加密和自定义哈希算法等核心组件。文章提供完整代码示例,涵盖GUID生成、参数构造和异步请求处理,帮助开发者掌握现代视频平台的反爬机制破解方法。

weixin_42532473的博客 1131

【如何学习CAN总线测试】——Python+Robot Framework框架实现UDS诊断自动化

由于项目需要进行UDS诊断测试,所以对这方面进行了研究学习,网上很少能查询到相关资料,故记录一下UDS自动化测试开发过程,由于保密原则,案例都是Demo,希望能帮到感兴趣的朋友。

测试领域技术分享 7470

iOS 7 present/dismiss自定义转场动画

前言 iOS 7以后提供了自定义转场动画的功能,我们可以通过遵守协议完成自定义转场动画。本篇文章讲解如何实现自定义present、dismiss自定义动画。 关于自定义push/pop转场动画,请阅读iOS 7 push/pop自定义转场动画 效果图 本篇文章实现的动画切换效果图如下: 视图切换种类 如...

weixin_34226182的博客 484

【教程4>第6章>第26节】基于FPGA的MMSE信道估计与均衡系统实现与整体测试,并对比LS信道估计

通过前面几个章节的学习,我们完成了MMSE信道估计和均衡系统。为了进一步验证MMSE信道估计的性能,我们在系统的最后,增加一个信道估计误差计算程序。由于MMSE信道估计,其主要优势在SNR较小时提现,因此测试对比时,我们在testbench中,将SNR设置为2db。然后m值,我们不考虑一个固定值,而是一直累加,直到所设置的仿真时间结束。通过对比可以看到,MMSE信道估计性能优于LS信道估计。这样方便FPGA中的误差计算。

FPGA/MATLAB学习教程/源码/项目合作开发 1600

UIVIewController自定义切换效果

iOS中常见的viewController切换有四种:模态视图,导航栏控制器,UITabBarController以及addChildViewController,自定义viewController动画切换也是iOS7中的新特性,常见的操作如下: 一、基本介绍 熟悉SDK中有关这部分内容的相关接口以及它们的关系和典型用法。相关的内容都定义在UIKit的UIViewControllerTransiti

xiaoxiaobukuang的专栏 1135

YOLO11改进|卷积篇|引入多样化分支块DBB

YOLO11中添加多样化分支块DBB

A1983Z的博客 1449

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

iOS 7学习:定制View Controllers之间的切换动画

原文地址:http://blog.youkuaiyun.com/jymn_chen/article/details/18944323 iOS 7新出了一个非常好玩的特性,就是View Controllers之间的切换动画,开发者也可以在程序中自行定制切换动画,例如翻转视图、缩放视图、旋转视图等等。另一方面,对于iPhone的使用来说,通过pan手势pop回到之前的视图,使用起来无疑是非常方便的。最开

宋波的专栏 644

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

视图控制器转场

自定义动画 iOS 7 对我来说最激动人心的特性就是新的视图控制器切换API(View Controller Transitioning API)。 iOS 7 之前,View Controller之间切换,我需要创建自定义的transitions。 而且这些方法都支持不完整,让人头疼。在transitions中增加交互功能就更难了。 在开始这篇文章之前,我要提醒一下:这是一个新的AP

yongyinmg的专栏 1180

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

iOS 7 新特性:视图控制器切换API

本文转载至http://blog.jobbole.com/51588/ 本文由伯乐在线-studentdeng翻译自Chris Eidhof。欢迎加入技术翻译小组。转载请参见文章末尾处的要求。 自定义动画 iOS 7 对我来说最激动人心的特性就是新的视图控制器切换API(View Controller Transitioning API)。 iOS 7 之前,View Co...

weixin_30699463的博客 59

iOS7中的ViewController切换

转自:https://onevcat.com/2013/10/vc-transition-in-ios7/ iOS 7 SDK之前的VC切换解决方案 在深入iOS 7的VC切换效果的新API实现之前,先让我们回顾下现在的一般做法吧。这可以帮助理解为什么iOS7要对VC切换给出新的解决方案,如果您对iOS 5中引入的VC容器比较熟悉的话,可以跳过这节。 在iOS5和iOS6中,除了标准的Pus...

weixin_30260399的博客 121

视图控制器切换API

自定义动画 iOS 7 对我来说最激动人心的特性就是新的视图控制器切换API(View Controller Transitioning API)。 iOS 7 之前,View Controller之间切换,我需要创建自定义的transitions。 而且这些方法都支持不完整,让人头疼。在transitions中增加交互功能就更难了。 在开始这篇文章之前,我要提醒一下:这是一个新的AP

code life 696

UIVIewController自定义切换效果-b

      之前介绍动画时提过UIView的转场动画,但是开发中我们碰到更多的viewController的切换,ios中常见的viewcontroller切换有四种:模态视图,导航栏控制器,UITabBarController以及addchildviewcontroller,自定义viewcontroller动画切换也是ios7中的新...

weixin_34405557的博客 118

Project-Tyson项目常见问题解决方案

Project-Tyson项目常见问题解决方案 1. 项目基础介绍和主要编程语言 Project-Tyson 是一个有关在 HTML、CSS 和 JavaScript 中伪造 iOS 7 用户界面的项目。该项目利用前端技术重现了 iOS 7 的界面样式和一些交互效果,让开发者能够在网页上模拟出 iOS 7 的视觉和操作体验。 主要编程语言 HTML:用于构建网页的结构。 CSS:用于设置页面的样...

gitblog_01146的博客 712

【IOS开发基础系列】UIViewController专题

1 UIViewController机制1.1 生命周期 UIViewController生命周期 理解view的生命周期:在UIViewController中,view(黑体的view指的是controller的view属性)有两个循环:加载和卸载循环。当程序的一部分向controller请求view的指针且view不在内存中时,view会进入加载循环,contro...

junbaozi的专栏 252
上一篇: iOS7 适配
下一篇: iOS7 icon 及 splash 页面大小
皓浩
博客等级 码龄18年 157粉丝 121原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值