详解 iOS 系统中的视图动画

动画为用户界面的状态转换提供了流畅的可视化效果, 在 iOS 中大量使用了动画效果, 包括改变视图位置、 大小、 从可视化树中删除视图, 隐藏视图等。 你可以考虑用动画效果给用户提供反馈或者用来实现有趣的特效。

在 iOS 系统中, Core Animation 提供了内置的动画支持, 创建动画不需要任何绘图的代码, 你要做的只是激发指定的动画, 接下来就交给 Core Animation 来渲染, 总之, 复杂的动画只需要几行代码就可以了。

哪些属性可以添加动画效果

根据 iOS 视图编程指南中说明, UIView 内置支持为下列属性添加动画效果:

  • Frame 可以改变视图相对于上一级视图的位置和大小。 (如果视图已经经过了缩放、 旋转、平移之类的变换, 则需要修改 Center 和 Bounds 属性)
  • Bounds 改变视图大小。
  • Center 改变视图相对于上级视图的位置。
  • Transform 相对于中心点进行视图缩放、旋转和平移, 这个属性只能进行二维转换。 (如果要进行三维转换, 则必须用 CoreAnimation 操作视图的 Layer 属性。)
  • Alpha 改变视图的透明度。
  • BackgroundColor 修改视图的背景色。
  • ContentStretch 改变视图内容在视图的可用空间内的拉伸方式。

为视图的属性变化添加动画

为了给属性的变化添加动画效果, 需要把修改这些属性的代码放到指定的动画代码段 (animation block) 中。 只有在动画代码段中修改支持动画的属性, 才能添加动画效果。

使用 Begin/Commit 方法做动画

在 iOS 3.0 以及之前的系统中, 必须使用 UIView 的类方法 beginAnimations:context: 和 commitAnimations 来定义动画代码段, 在 begin 和 commit 之间的代码会在特殊的动画线程中运行, 因此不会阻塞主线程, 比如说要切换两个视图, 代码应该是这样子的:

[UIView beginAnimations:@"ToggleViews" context:nil];
[UIView setAnimationDuration:1.0];

// Make the animatable changes.
firstView.alpha = 0.0;
secondView.alpha = 1.0;

// Commit the changes and perform the animation.
[UIView commitAnimations];

在 Xamarin.iOS (MonoTouch) 平台下, begin/end 方法对应的绑定为:

  • public static void BeginAnimations (string animation)
  • public static void BeginAnimations (string animationID, IntPtr context)
  • public static void CommitAnimations ()

上面的切换视图的 C# 版本代码为:

UIView.BeginAnimations("ToggleViews");
UIView.SetAnimationDuration(1.0)
this.FirstView.Alpha = 0.0;
this.SecondView.Alpha = 1.0;
UIView.CommitAnidations();

在 Begin/Commit 函数之间, 可以通过下面的方法设置动画的参数和选项:

  • setAnimationStartDate:
  • setAnimationDelay:
  • setAnimationDuration:
  • setAnimationCurve:
  • setAnimationRepeatCount:
  • setAnimationRepeatAutoreverses:
  • setAnimationDelegate:
  • setAnimationWillStartSelector:
  • setAnimationDidStopSelector:
  • setAnimationBeginsFromCurrentState:

注意: 如果不是为了支持很旧的设备, 则推荐使用下面的 lambda (block based method) 来实现动画效果, 虽然 begin/commit 还能够使用, 按照官方的说法, 对新系统来说是不推荐的了。

使用 lambda (block based method) 做动画

在 iOS 4.0 以后, 引入了代码块 (code block) 的概念, 可以使用代码块来初始化动画, 这也是在 iOS 4.0 之后苹果推荐的做法, iOS SDK 提供的 API 如下:

  • animateWithDuration:animations:
  • animateWithDuration:animations:completion:
  • animateWithDuration:delay:options:animations:completion:

而在 Xamarin.iOS (MonoTouch) 平台下, 这些方法被绑定为下列方法:

  • public static void Animate(double duration, NSAction animation)
  • public static void Animate (double duration, NSAction animation, NSAction completion)
  • public static void Animate (double duration, double delay, UIViewAnimationOptions options, NSAction animation, NSAction completion)

还是切换视图的动画, 如果用 objective-c 的代码块来实现, 则应该是这样子的:

[UIView animateWithDuration:1.0 animations:^{
  self.firstView.alpha = 0.0;
  self.secondView.alpha = 1.0;
}];

如果用 C# 来实现的话, 应该是这样:

UIView.Animate(1.0, () => {
  this.FirstView.Alpha = 0.0f;
  this.SecondView.Alpha = 1.0f;
});

这样就实现了一个简单的渐变动画, 并且只能运行一次, 通常不能满足需求, 再来一个复杂点儿的:

[UIView animateWithDuration:1.0
    delay:0.0
    options:UIViewAnimationOptionCurveEaseIn
    animations:^{
      self.firstView.alpha = 0.0;
    }
    completion:^(BOOL finished){
      [UIView animateWithDuration:1.0
          delay:1.0
          options:UIViewAnimationOptionCurveEaseOut animations:^{
            self.firstView.alpha = 1.0;
          }
          completion:nil];
}];

对应的 C# 代码如下:

UIView.Animate(
  1.0,
  0.0,
  UIViewAnimationOptions.CurveEaseIn,
  () => this.FirstView.Alpha = 0.0f,
  () => {
    UIView.Animate(
      1.0,
      1.0,
      UIViewAnimationOptions.CurveEaseOut,
      () => this.FirstView.Alpha = 1.0f,
      null
    );
  }
);

嵌套动画

iOS 支持嵌套的动画, 也就是说在一个动画代码段中, 可以再开始另外一个动画代码段, 而不必等当前动画完成, 嵌套的动画会同时开始运行, 默认继承原来动画的延时、 时间长度、 加速曲线等, 不过这些选项也能被覆盖。 例如:

[UIView animateWithDuration:1.0
  delay:1.0
  options:UIViewAnimationOptionCurveEaseOut animations:^{
    self.firstView.alpha = 0.0f;
    // 这里开始一个新的动画
    [UIView animateWithDuration:1.0
      delay:0.0
      options:UIViewAnimationOptionOverrideInheritedCurve |
        UIViewAnimationOptionCurveLinear |
        UIViewAnimationOptionOverrideInheritedDuration |
        UIViewAnimationOptionRepeat |
        UIViewAnimationOptionAutoreverse
      animations:^{
        [UIView setAnimationRepeatCount:2.5];
        self.secondView.alpha = 0.0f;
      }
      completion:nil];
  }
  completion:nil
];

对应的 C# 代码如下:

UIView.Animate(
  1.0,
  1.0,
  UIViewAnimationOptions.CurveEaseIn,
  () => {
    this.FirstView.Alpha = 0.0;
    UIView.Animate(
      1.0,
      1.0,
      UIViewAnimationOptions.OverrideInheritedCurve |
      UIViewAnimationOptions.CurveLinear |
      UIViewAnimationOptions.OverrideInheritedDuration |
      UIViewAnimationOptions.Repeat |
      UIViewAnimationOptions.Autoreverse,
      () => {
        UIView.SetAnimationRepeatCount(2.f);
        this.SecondView.Alpha = 0.0;
      },
      null
    );
  },
  null
);

对于使用 Begin/Commit 方法的动画, 也可以嵌套调用 Begin/Commit 方法来实现嵌套的动画, 例如:

UIView.BeginAnimations("Animation1");
// Animation code goes here
  // Start another animation
  UIView.BeginAnimations("Nested animation");
  // nested animations code goes here.
  UIView.CommitAnimations();
// other code
UIView.CommitAnimations();

这段 C# 代码对应的 ObjC 代码很简单, 就不写出来了。

实现动画的自动翻转

当创建自动翻转指定次数的动画时, 考虑将重复次数设置为非整数值。 因为对于自动翻转的动画来说, 每次循环都是从原始值变化到目标值再变化回原始值, 如果希望动画结束之后停留在目标值, 需要将重复次数设置加上 0.5 , 否则, 动画回慢慢变回原始值, 再迅速变化到目标值, 这可能不是原来期望的动画效果。

创建视图切换动画

视图切换动画可以减少修改可视化树时引起的界面上的突变, iOS 系统中大量使用了视图切换动画, 视图切换动画主要有下面两种场景:

  • 修改子视图
  • 替换子视图

注意: 不要把视图切换和视图控制器的切换混淆(显示一个模式对话框、将视图控制器推入导航堆栈等), 视图切换改变的仅仅是视图的可视化树, 视图控制器是不变的, 更多信息可以参考iOS视图控制器编程指南。

修改子视图

可以修改子视图的可见性用来表示当前视图的不同的状态, 看下面的两个视图切换的例子,在 iOS 4.0 之前, 需要将视图切换动画添加到 Begin/Commit 动画之间, 代码如下:

在 iOS 4.0 之后, 可以使用 transitionWithView:duration:options:animations:completion:

[UIView beginAnimations:@"toggleView" context:nil];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
[UIView setAnimationDuration:1.0];
// animation goes here
self.currentView.hidden = YES;
self.swapView.hidden = NO;
[UIView commitAnimations];

这里只有动画部分的代码, 动画完成之后请参考 setAnimationDelegate: 方法设置并实现 UIAnimationDelegate 。

替换子视图

要进行子视图的替换, 需要用到 transitionFromView:toView:duration:options:completion: 方法, 示例代码如下:

UIView *fromView = (self.displayPrimary ? self.view : self.secondView);
UIView *toView = (self.displayPrimary ? self.secondView : self.view);
UIViewAnimationOptions option = (self.displayPrimary ? UIViewAnimationOptionTransitionFlipFromRight
                : UIViewAnimationOptionTransitionFlipFromLeft);
[UIView transitionFromView:fromView toView:toView duration:1.0 options:option
  completion:^(BOOL finished) {
    if (finished) {
    self.displayPrimary = !self.displayPrimary;
    }
  }
];

链接多个动画

有了上面的知识, 链接多个动画就非常简单了:

  • 对于 lambda 或 block-based 方法的动画, 使用 complete 回调函数即可;
  • 对于 Begin/Commit 方法的动画, 需要实现一个 UIAnimationDelegate , 然后调用 setAnimationDelegate 方法设置 Delegate 即可。

以上就是详解 iOS 系统中的视图动画的详细内容,更多关于iOS 视图动画的资料请关注我们其它相关文章!

(0)

相关推荐

  • iOS实现转场动画的3种方法示例

    什么是转场动画 在 NavigationController 里 push 或 pop 一个 View Controller,在 TabBarController 中切换到其他 View Controller,以 Modal 方式显示另外一个 View Controller,这些都是 View Controller Transition.在 storyboard 里,每个 View Controller 是一个 Scene,View Controller Transition 便是从一个 Sce

  • iOS仿AirPods弹出动画

    本文实例为大家分享了iOS仿AirPods弹出动画的具体代码,供大家参考,具体内容如下 效果图 预览图 思路 在当前ViewController下Present另外一个AnimationViewController,在弹出的AnimationViewController中播放动画,弹出的时候原来的ViewController上有一个全屏覆盖的maskView,在弹出时,有一个渐变动画(页面渐黑),在AnimationViewController声明一个代理,在代理方法中实现收起的动画效果(dis

  • iOS仿抖音视频加载动画效果的实现方法

    前言 这几天一直跟开源的抖音demo斗智斗勇,今天跟大家分享的是抖音中或者快手中加载视频的动画,这个加载效果还是挺实用,下面话不多说了,来随着小编一起学习学习吧 上图看成品 实现原理 首先我创建一个视图 @interface ViewController () @property (nonatomic, strong) UIView *playLoadingView; @end @implementation ViewController - (void)viewDidLoad { [super

  • iOS实现数字倍数动画效果

    前言 一个简单的利用 透明度和 缩放 实现的 数字倍数动画 效果图: 实现思路 上代码 看比较清晰 // 数字跳动动画 - (void)labelDanceAnimation:(NSTimeInterval)duration { //透明度 CABasicAnimation *opacityAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"]; opacityAnimation.duration = 0.4 * d

  • iOS自定义UIButton点击动画特效

    借鉴相关资料,整理了一个很有意思的button动画效果,iOS自定义UIButton点击动画特效 先看一下效果图: 下面贴上代码: ViewController: #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end #import "ViewController.h" #import "HWButton.h" #define mainW [UIScreen m

  • iOS基于CATransition实现翻页、旋转等动画效果

    基于CATransition实现翻页.旋转.淡化.推进.滑入滑出.立方体.吮吸.波纹等动画效果. 首先看一下效果图: 下面贴上代码: #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end #import "ViewController.h" //获得屏幕的宽高 #define mainW [UIScreen mainScreen].bounds.size.width #define

  • iOS实现抖音点赞动画效果

    本文实例为大家分享了iOS实现抖音点赞动画的具体代码,供大家参考,具体内容如下 1. 概述 最近看到抖音点赞爱心的动画效果比较好,出于好奇,自己也研究仿照动画效果写了一个,不喜欢的朋友可不要喷我噢!!! 话不多说,先来看一下执行效果. 2. 动画分析 上面的示例效果有点快,现在来看一个慢的,然后在分析动画组成. 这回看清楚了吧,哈哈. 2.1 动画过程分析 咱们就以10秒的点赞动画来分析一下: 点赞的时候: 1.点击的时候,白色爱心逐渐变小到一定程度,然后变成红色爱心.(3秒) 2.红色爱心慢慢

  • iOS实现点赞动画特效

    本文实例为大家分享了iOS实现点赞动画特效的具体代码,供大家参考,具体内容如下 动画的基本使用 动画的实现基本上是基于对View控件和View的layer属性进行操作,对视图进行移动,尺寸变换,透明度变换,旋转等一系列操作. 关键帧动画: 动画的实现可以分为两个部分,一部分是规定动画的变化内容,比如view需要把scale从0变化到1,这个数字是相对值,即从尺寸为0变化到正常尺寸.另一个部分是规定动画的渐变时间.这样就实现了view在规定时间完成指定变化了,这个变化的过程也可以通过参数设置为非均

  • iOS如何优雅地实现序列动画详解

    前言 我们的在做动效中经常会有这样的需求,A动画执行完,执行B动画,B动画执行完执行C动画这样的序列,比如如下效果: iOS 10之前,我们可能这样实现这个动画序列,实际上可能你现在的代码就是这样写的: UIView.animate()提供了一个完成block回调,我们可以用它来触发下一个动画.这样做,我们可以实现这个动画.正如你可以看到的,这坨代码的主要缺点是丑陋,几乎没有可读性. UIViewPropertyAnimator iOS10引入了UIViewPropertyAnimator ,基

  • iOS仿微博导航栏动画(CoreGraphics)的实现方法

    前言 昨天刚做完项目的新版本.除了尝试一些新的架构之外.功能方面并没什么特别的地方. 但是顺手搞了一些还算好玩的东西.其一就是这个导航栏的动画. 感觉还算简单易懂.分享一下(其实更多是最近攒了好多封面.不贴出来憋得人难受). 导航栏动画.gif 思路 先介绍CA的两个方法: 基于原始状态的位移 CG_EXTERN CGAffineTransform CGAffineTransformMakeTranslation(CGFloat tx, CGFloat ty) CG_AVAILABLE_STAR

  • iOS自定义转场动画的几种情况

    前言 在开发中,无论我们使用 Push 还是 Present 推出新的 ViewController 时,系统为了提高用户体验都会为我们默认加上一些过渡动画.但是,系统默认的动画总是不能满足大家各种各样的需求的,所以系统也为我们提供了在不同场景下自定义过渡动画以及通过手势控制过渡进度的实现方案. 这篇文章记录了自定义转场动画中的几种情况: 模态跳转(Present) 导航控制器跳转(Push) UITabbarController 三方框架--Lottie 效果图 预备 首先,我们现在介绍几个在

随机推荐