前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS 系统中的视图动画

iOS 系统中的视图动画

作者头像
beginor
发布2020-08-10 11:08:19
2.2K0
发布2020-08-10 11:08:19
举报

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 之间的代码会在特殊的动画线程中运行, 因此不会阻塞主线程, 比如说要切换两个视图, 代码应该是这样子的:

代码语言:javascript
复制
[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 方法对应的绑定为:

代码语言:javascript
复制
public static void BeginAnimations (string animation)
public static void BeginAnimations (string animationID, IntPtr context)
public static void CommitAnimations ()

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

代码语言:javascript
复制
UIView.BeginAnimations("ToggleViews");
UIView.SetAnimationDuration(1.0)
this.FirstView.Alpha = 0.0;
this.SecondView.Alpha = 1.0;
UIView.CommitAnidations();

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

代码语言:javascript
复制
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 如下:

代码语言:javascript
复制
animateWithDuration:animations:
animateWithDuration:animations:completion:
animateWithDuration:delay:options:animations:completion:

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

代码语言:javascript
复制
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 的代码块来实现, 则应该是这样子的:

代码语言:javascript
复制
[UIView animateWithDuration:1.0 animations:^{
    self.firstView.alpha = 0.0;
    self.secondView.alpha = 1.0;
}];

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

代码语言:javascript
复制
UIView.Animate(1.0, () => {
    this.FirstView.Alpha = 0.0f;
    this.SecondView.Alpha = 1.0f;
});

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

代码语言:javascript
复制
[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# 代码如下:

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

代码语言:javascript
复制
[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# 代码如下:

代码语言:javascript
复制
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 方法来实现嵌套的动画, 例如:

代码语言:javascript
复制
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:

代码语言:javascript
复制
[UIView transitionWithView:self.view
    duration:1.0
    options:UIViewAnimationOptionTransitionCurlUp
    animations:^{
        self.currentView.hidden = YES;
        self.swapView.hidden = NO;
    }
    completion:^(BOOL finished) {
        UIView *tmp = self.currentView;
        self.currentView = self.swapView;
        self.swapView = tmp;
    }
];

在 iOS 4.0 之前需要用到的函数是 setAnimationTransition:forView:cache: 对应的代码如下:

代码语言:javascript
复制
[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: 方法, 示例代码如下:

代码语言:javascript
复制
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 即可。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • iOS 系统中的视图动画
    • 哪些属性可以添加动画效果
      • 为视图的属性变化添加动画
        • 使用 Begin/Commit 方法做动画
        • 使用 lambda (block based method) 做动画
        • 嵌套动画
        • 实现动画的自动翻转
      • 创建视图切换动画
        • 修改子视图
        • 替换子视图
      • 链接多个动画
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档