美文网首页
View Animations(三)Transitions

View Animations(三)Transitions

作者: iYeso | 来源:发表于2017-12-07 15:20 被阅读9次

    Transitions

    在前两章中,您学习了如何基于视图的动画属性(如位置和alpha)创建动画。但是,如何处理想要增加或删除视图的情况呢?

    您可以使用前面章节中的方法,并在界面中进出视图。不过,本章将向您展示如何使用转换为视图的任何一组更改设置动画

    转场是可以应用于视图的预定义动画。这些预定义的动画不会尝试在视图的开始和结束状态之间进行插值。相反,您将设计动画,以便各种状态的变化显得自然

    一: Transitions实例

    为了更好地理解何时使用过渡动画,本节将向您介绍可以使用Transitions动画的各种动画场景

    添加一个视图

    image

    要在屏幕上添加一个新视图的动画,可以调用与前面章节中使用的方法类似的方法。这次的区别在于你会选择一个预定义的过渡效果,并为所谓的动画容器视图设置动画效果

    该过渡为容器视图添加了动画,并且在动画运行时,添加到视图的任何新视图都以子视图的形式出现

    为了更好地解释如何为容器视图设置动画,以及何时执行子视图之间的转换,请考虑以下代码片段:

    var animationContainerView: UIView!
    override func viewDidLoad() {
      super.viewDidLoad()
      //set up the animation container
      animationContainerView = UIView(frame: view.bounds)
      animationContainerView.frame = view.bounds
      view.addSubview(animationContainerView)
    }
    override func viewDidAppear(_ animated: Bool) {
      super.viewDidAppear(animated)
      //create new view
      let newView = UIImageView(image: UIImage(named: "banner"))
      newView.center = animationContainerView.center
      //add the new view via transition
      UIView.transition(with: animationContainerView,
        duration: 0.33,
         options: [.curveEaseOut, .transitionFlipFromBottom],
        animations: {
          self.animationContainerView.addSubview(newView)
        },
        completion: nil
      )
    }
    

    在这种假设的情况下,您在视图控制器的viewDidLoad()中创建一个名为animationContainerView的新视图。 然后您定位并将此容器添加到视图

    稍后,当您要创建动画过渡时,您将创建一个新的视图来进行动画处理; 这里叫做newView

    要创建转换,请调用transition(with:duration: options:animations:completion:)。 这和标准的UIView动画方法几乎是一样的,但是在这种情况下,你提供了一个额外的参数视图,它作为过渡动画的容器视图

    这里有一个新的动画选项.transitionFlipFromBottom,你还没有看到。 这是本章介绍中讨论的预定义转换之一. .transitionFlipFromBottom翻转视图的底部边缘作为视图翻转的“hinge”

    最后,你在你的动画块中的动画容器中添加一个子视图,这会导致子视图在转换过程中出现

    预定义过渡动画选项的完整列表如下所示:

    • .transitionFlipFromLeft
    • .transitionFlipFromRight
    • .transitionCurlUp
    • .transitionCurlDown
    • .transitionCrossDissolve
    • .transitionFlipFromTop
    • .transitionFlipFromBottom

    移除视图(Removing a view)

    image
    使用过渡动画从屏幕中删除子视图非常类似于添加子视图。要使用过渡动画完成此操作,只需在动画闭包表达式中调用removeFromSuperview()就可以了
    //remove the view via transition
    UIView.transition(with: animationContainerView, duration: 0.33,
      options: [.curveEaseOut, .transitionFlipFromBottom],
      animations: {
        self.newView.removeFromSuperview()
      },
      completion: nil
    )
    

    和前面的例子一样,包装器转换将执行翻转动画,newView将在所有的结尾消失。

    隐藏和展示视图(Hiding/showing a view)
    [站外图片上传中...(image-7401e1-1512631213095)]

    到目前为止,在本章中,您只学习了改变视图层次结构的转换。 这就是为什么你需要一个容器视图的过渡 - 这使得层次结构的变化在上下文中

    相比之下,您不需要担心设置容器视图来隐藏和显示观点。 在这种情况下,转换使用视图本身作为动画容器

    考虑下面的代码来使用转换来隐藏子视图:

    //hide the view via transition
    UIView.transition(with: self.newView, duration: 0.33,
      options: [.curveEaseOut, .transitionFlipFromBottom],
      animations: {
        self.newView.isHidden = true
      },
      completion: nil
    )
    

    在这里你传入你想要显示或隐藏的视图作为转换的第一个参数transition(with:duration:options:animations:completion:)。 你之后所做的就是在动画块中设置你的视图的isHidden属性,并且瞧,过渡动画开始

    替代视图(Replacing a view with another view)

    image

    用另一个视图替换一个视图也是一个简单的过程。您只需传入现有视图作为第一个参数,并将toView:参数设置为您希望替换的视图,如下所示

    //replace via transition
    UIView.transition(from: oldView, to: newView, duration: 0.33,
      options: .transitionFlipFromTop, completion: nil)
    

    UIKit为您提供了多少重要的功能?

    在本章的其余部分中,您将通过转换来展示和隐藏UI元素,并学习一些可以引入自己的项目的新动画技巧

    二: (混合转场)Mixing in transitions

    您将继续在本章中的Bahama Air登录屏幕项目上工作; 你已经创建了一些引人注目的动画在这个屏幕上的意见,添加一点点的登录表单,并使按钮反应被挖掘

    接下来,您将模拟一些用户身份验证并为几个不同的进度消息添加动画。一旦用户点击登录按钮,您将显示消息,包括“Connecting...”,“Authorizing...”和“Failed”

    image

    如果您还没有完成前面的章节,您可以从本章的资源文件夹中的入门项目开始。如果你已经在自己的项目的最后几章中的例子,很好的工作! 您可以继续使用现有的项目

    打开ViewController.swift并查看viewDidLoad(),这种方法的一部分添加了一个隐藏的图像视图存储在类变量状态。代码然后创建一个文本标签,并将其作为子视图添加到状态

    您将使用状态向用户显示进度消息。 消息来自消息数组,这是starter项目中包含的另一个类变量。

    将以下方法添加到ViewController

    func showMessage(index: Int) {
      label.text = messages[index]
      UIView.transition(with: status, duration: 0.33,
        options: [.curveEaseOut, .transitionCurlDown],
        animations: {
          self.status.isHidden = false
        },
        completion: {_ in
                //transition completion
      } )
    }
    

    这个方法带有一个名为index的参数,你可以使用它来将label的值设置为基于index的消息内容

    上面还有一个新的动画选项:.transitionCurlDown,这种过渡使得视图像一张纸在合法的平板上被翻转一样,看起来像下面一样

    image

    现在是时候锻炼你的新showMessage(index :)方法。 在login()中找到以下代码块:

    animations: {
      self.loginButton.bounds.size.width += 80.0
    }, completion: nil)
    

    这是您现有的动画块,当用户点击它时,会使登录按钮反弹。 你会添加一些新的东西 - 一个完成封闭 - 这个动画,调用showMessage(index:).

    将完成的nil参数值替换为以下闭包表达式:

    completion: { _ in
      self.showMessage(index: 0)
    }
    

    闭包需要一个Bool参数,它告诉你动画是否成功完成,或者在动画完成之前被取消

    注意:上面的完成关闭具有完成的单个参数。因为你不关心它是否完成,Swift允许你跳过绑定参数,把“_”放在它的位置。

    在闭包中,只需调用索引为0的showMessage即可显示消息数组中的第一条消息

    建立并运行你的项目; 点击登录按钮,你会看到状态标题出现你的第一个进度信息
    [站外图片上传中...(image-e206e0-1512631213095)]

    你看到横幅像一张纸一样卷起来了吗? 这是一个非常好的方式来关注通常只显示为静态文本标签的消息。

    注意:你的一些动画似乎很快运行,不是吗?有时确保动画在正确的位置以正确的顺序发生是非常棘手的。 或者,也许你只是想让事情发生得更慢,所以你可以欣赏效果!要在不改变代码的情况下减慢应用程序中的所有动画,请从iPhone Simulator菜单中选择“最前面的应用程序中的调试/切换慢动画”。 现在点击您的应用程序中的登录按钮,享受生动的慢动作的动画和过渡!

    对于下一个动画,您首先需要保存横幅的初始位置,以便您可以将下一个横幅放在正确的位置。

    将以下代码添加到viewDidLoad()的末尾,将横幅的初始位置保存到名为statusPosition的属性中:

      statusPosition = status.center
    

    现在,您可以开始设计视图动画和过渡的混合。

    添加以下方法通过标准从屏幕上删除状态消息动画:

    func removeMessage(index: Int) {
      UIView.animate(withDuration: 0.33, delay: 0.0, options: [],
        animations: {
          self.status.center.x += self.view.frame.size.width
        },
        completion: { _ in
          self.status.isHidden = true
          self.status.center = self.statusPosition
          self.showMessage(index: index+1)
        }
    ) }
    

    在上面的代码中,您可以使用您的老朋友animate(withDuration:delay:options:animations:completion:)将状态移动到屏幕可见区域之外。

    当动画在完成关闭时完成时,将状态移回原始位置并隐藏。 最后你再次调用showMessage,但这次你传递下一条消息的索引来显示

    将标准动画与转换相结合非常容易:只需调用相应的API,UIKit就会调用背景中相应的Core Animation

    现在,您需要完成showMessageremoveMessage之间的调用链,以模拟真实的身份验证过程

    找到showMessage(index :)并用下面的代码替换注释//转换完成:

    delay(2.0) {
      if index < self.messages.count-1 {
        self.removeMessage(index: index)
      } else {
    //reset form
    } }
    

    一旦转换完成,你等待2.0秒,并检查是否有任何剩余的消息。如果是这样,通过removeMessage(index :)删除当前消息。 然后,您可以在removeMessage(index :)
    的完成块中调用showMessage(index :)来按顺序显示下一条消息。

    注意:delay(_:completion :)是一个方便的函数,在经过延迟后运行一段代码。 它在ViewController.swift的顶部定义。 在这里你用它来模拟通常的网络访问延迟。

    再次构建并运行您的项目; 享受由此产生的动画序列,其如此更新认证进程消息
    [站外图片上传中...(image-e6c9b9-1512631213095)]

    转换是动画知识的一个小而重要的子集,以保留在你的比喻工具箱中,因为它们是在UIKit中创建3D风格动画的唯一方法。

    如果您期待学习更精细的3D效果,您将有机会在第六部分“3D动画”中详细讨论Core

    在进入下一部分之前,请尝试尝试本章中的挑战。既然你在前三章学到了很多关于动画的知识,一个挑战是不够的 - 我给了你三个Animation和3D图层转换。

    这些挑战使您有机会在Bahama Air登录屏幕上完成开发工作 - 同时也是您面临的第一个挑战。活泉!

    #######挑战

    挑战一
    到目前为止,您只能看到其中一个内置的过渡动画。 你不是很好奇看到别人是什么样子吗?

    在这个挑战中,你可以尝试所有其他可用的过渡动画,并使用你最喜欢的动画进度信息横幅

    打开ViewController并在showMessage(index :)中找到指定过渡动画的行.transitionCurlDown`

     UIView.transitionWithView(status, duration: 0.33, options:
      [.curveEaseOut, .transitionCurlDown], an
    

    .transitionCurlDown替换为其他任何可用的过渡动画,然后构建并运行项目以查看它们的外观。 以下是可用转换的列表:

    .transitionFlipFromLeft
    .transitionFlipFromRight
    .transitionCurlUp
    .transitionCurlDown
    .transitionCrossDissolve
    .transitionFlipFromTop
    .transitionFlipFromBottom
    

    哪一个你认为在这个屏幕上的其他动画效果最好?
    如果你没有最爱,请尝试我的最爱过渡:.transitionFlipFromBottom。 我认为它非常适合横幅图形:

    image

    挑战二
    对于这个挑战,您可以通过撤消一旦点击登录按钮后运行的所有动画,将表单重置为初始状态。 这样,如果登录失败,当用户再次点击登录按钮时,他们会看到所有的动画再次发生

    以下列出了完成这一挑战所需的一般步骤:

    • 1:创建一个新的空方法resetForm()并从你的代码中调用它占位符评论//重置表单的生命。
    • 2:在resetForm()中使用transition(with:duration:options:animations:completion :)将状态的可见性设置为隐藏和居中为self.statusPosition。 这应该重置旗帜到其初始状态。 使用0.2秒的时间进行转换。
    • 3: 如果隐藏横幅的转换使用与显示横幅的动画完全相反的动画,那将会很好。 例如,如果您通过.transitionCurlDown显示横幅,则使用.transitionCurlUp将其隐藏。 相反
      .transitionFlipFromBottom将是.transitionFlipFromTop...等等
    • 4: 接下来,在resetForm()中添加一个对animate(withDuration:delay:options:animations:completion :)的调用。 在动画闭包模块中进行以下调整
      • self.spinner(“登录”按钮内的活动指示器)移动到(-20.0,16.0)的原始位置,
      • self.spinneralpha属性设置为0.0以隐藏它。
      • 将“登录”按钮的背景颜色调回原始值:UIColor(red: 0.63, green: 0.84, blue: 0.35, alpha: 1.0).
      • 继续重置对“登录”按钮的所有更改,然后减小由80.0点的bounds.size.width属性
      • 最后,将该按钮移回密码字段下的原始位置减少60.0点

    如果您在身份验证过程中精确地颠倒了所有的动画,屏幕一旦所有的认证信息都显示出来,
    [站外图片上传中...(image-c2bfe3-1512631213095)]

    做得好! 而现在这一章的über挑战...

    [站外图片上传中...(image-571d0-1512631213095)]

    关于挑战:在背景中动画云彩
    如果背景中的那些云在屏幕上慢慢地移动,并从另一侧再次出现,这不是很酷吗?
    是的,这将是非常酷 - 这就是你的挑战!

    四个云图像视图已经连线到ViewController的四个插座,所以你很好走。 你可以尝试使用你自己新发现的过渡动画知识来自己动手,或者你可以按照下面的配方

    • 1: 创建一个签名为animateCloud(cloud:UIImageView)的新方法,并在其中添加代码。
    • 2: 首先,计算平均云速度。 假设云应该在大约60.0秒内穿过屏幕的整个长度。 调用常量cloudSpeed并将其设置为60.0/view.frame.size.width
    • 3: 接下来,计算动画将云移动到屏幕右侧的持续时间。 请记住,云不是从屏幕的左边缘开始,而是从随机点开始。 你可以计算正确的持续时间,通过考虑云需要遵循的路径的长度,并将结果乘以平均速度:`(view.frame.size.width - cloud.frame.origin.x)*cloudSpeed
    • 4: 然后调用animate(withDuration:delay:options:animation:completion :)以上面刚计算的持续时间。 您需要从中创建TimeInterval的实例,因为编译器不会为您确定正确的类型:TimeInterval(duration)。 对于选项参数使用.curveLinear; 这是少数几次使用动画而没有缓动的情况之一。 云层背景自然很深,所以他们的运动看起来应该是平坦的。
    • 5: 在动画闭包表达式中,将云的frame.origin.x属性设置为self.view.frame.size.width。 这将云移动到屏幕区域之外。
    • 6: 在完成关闭块内,将云从当前位置移动到屏幕另一边的外部。 不要忘记像本章前面所做的那样,使用“_”来跳过闭包参数。 要正确定位云,请将其frame.origin.x设置为-cloud.frame.size.width
    • 7: 仍然在完成关闭工作,添加一个调用animateCloud(),以便云重新在屏幕上动画。
    • 8: 最后,将以下代码添加到viewDidAppear()的末尾,以启动所有四个云的动画
    animateCloud(cloud1)
    animateCloud(cloud2)
    animateCloud(cloud3)
    animateCloud(cloud4)
    

    这应该使所有四个云彩慢慢地穿过屏幕创造一个好,不引人注目的作用。
    如果您完成了本章的挑战,恭喜! 他们很难!:]
    过去几章有很多信息需要消化,但是你采取了一种僵硬的,静态的登录表单,并将其转化为对用户的引人注目和有趣的体验:

    [站外图片上传中...(image-decc0f-1512631213095)]

    现在是时候从新材料中稍微休息一下,把所有的视图动画知识加入测试! 在下一章中,您将使用各种各样的实际操作来为Bahama Air应用程序添加一些严肃的优雅的动画。

    相关文章

      网友评论

          本文标题:View Animations(三)Transitions

          本文链接:https://www.haomeiwen.com/subject/qvndixtx.html