草庐IT

ios - 在支持层的 View 上使用核心动画

coder 2023-09-30 原文

Core Animation Programming guide ,有一段关于How to Animate Layer-Backed Views , 它说:

If you want to use Core Animation classes to initiate animations, you must issue all of your Core Animation calls from inside a view-based animation block. The UIView class disables layer animations by default but reenables them inside animation blocks. So any changes you make outside of an animation block are not animated.



还有一个例子:
[UIView animateWithDuration:1.0 animations:^{
   // Change the opacity implicitly.
   myView.layer.opacity = 0.0;

   // Change the position explicitly.
   CABasicAnimation* theAnim = [CABasicAnimation animationWithKeyPath:@"position"];
   theAnim.fromValue = [NSValue valueWithCGPoint:myView.layer.position];
   theAnim.toValue = [NSValue valueWithCGPoint:myNewPosition];
   theAnim.duration = 3.0;
   [myView.layer addAnimation:theAnim forKey:@"AnimateFrame"];
}];

在我看来,它表明如果我不在基于 View 的动画 block 内部发出 Core Animation 调用,则不会有动画。

但似乎如果我直接添加核心动画调用而没有基于 View 的动画 block ,它的工作原理是一样的。

我错过了什么吗?

最佳答案

tl;博士:该文档仅涉及隐式动画。显式动画在动画 block 之外运行良好。

我对文档的解释

文档中该引用的简化版本类似于(我对其进行了解释):

UIView have disabled implicit animations except for within animation blocks. If you want to do implicit layer animations you must do them inside an animation block.



什么是隐式动画,它们是如何工作的?

隐式动画是当独立层的可动画属性发生变化时发生的情况。例如,如果您创建一个图层并更改它的位置,它将动画到新位置。默认情况下,许多图层属性都具有此行为。

它发生这样的事情:
  • 系统启动了一个事务(没有我们做任何事情)
  • 属性的值被更改
  • 该层寻找该属性的操作
  • 在某个时间点事务被提交(没有我们做任何事情)
  • 应用找到的操作

  • 注意上面没有提到动画,而是有“ Action ”这个词。此上下文中的操作指的是实现 CAAction 的对象。协议(protocol)。它最有可能是某个 CAAnimation 子类(如 CABasicAnimation、CAKeyframeAnimation 或 CATransition),但它被构建为与任何符合该协议(protocol)的东西一起使用。

    它怎么知道要采取什么“行动”?

    通过调用 actionForKey: 来查找该属性的操作。层上。这个的默认实现按以下顺序查找操作:

    此搜索按此顺序进行(引用: actionForKey: documentation )

    1. If the layer has a delegate and that delegate implements the Accessing the Layer’s Filters method, the layer calls that method. The delegate must do one of the following:
      • Return the action object for the given key.
      • Return nil if it does not handle the action.
      • Return the NSNull object if it does not handle the action and the search should be terminated.
    2. The layer looks in the layer’s actions dictionary.
    3. The layer looks in the style dictionary for an actions dictionary that contains the key.
    4. The layer calls its defaultActionForKey: method to look for any class-defined actions.
    5. The layer looks for any implicit actions defined by Core Animation.


    UIView 在做什么?

    对于支持 View 的层, View 可以启用或禁用操作 by implementing the delegate method actionForLayer:forKey .对于正常情况(在动画 block 之外), View 通过返回 [NSNull null] 禁用隐式动画。意思是:

    it does not handle the action and the search should be terminated.



    然而,在动画 block 内, View 返回一个真实的 Action 。这可以通过手动调用 actionForLayer:forKey: 轻松验证。动画 block 的内部和外部。它也可以返回 nil这将导致图层继续寻找 Action ,如果在此之前找不到任何内容,最终会以隐式 Action (如果有)结束。

    当找到一个 Action 并提交事务时,使用常规 addAnimation:forKey: 将 Action 添加到层中。机制。这可以通过创建自定义图层子类并在 -actionForKey: 中登录来轻松验证。和 -addAnimation:forKey:然后是覆盖 +layerClass 的自定义 View 子类并返回自定义图层类。您将看到独立层实例记录了常规属性更改的两种方法,但支持层不会添加动画,除非在动画 block 中。

    为什么要对隐式动画进行这么长的解释?

    现在,为什么我要对隐式动画的工作原理给出这么长的解释?嗯,这是为了表明它们使用与您自己使用的显式动画相同的方法。知道它们是如何工作的,我们就可以理解文档说:“UIView 类默认禁用图层动画,但在动画 block 内重新启用它们”的含义。

    UIView 没有禁用显式动画的原因是您自己完成了所有工作:更改属性值,然后调用 addAnimation:forKey: .

    代码中的结果:

    动画 block 之外:
    myView.backgroundColor       = [UIColor redColor];           // will not animate :(
    myLayer.backGroundColor      = [[UIColor redColor] CGColor]; // animates :)
    
    myView.layer.backGroundColor = [[UIColor redColor] CGColor]; // will not animate :(
    [myView.layer addAnimation:myAnimation forKey:@"myKey"];     // animates :)
    

    动画 block 内部:
    myView.backgroundColor       = [UIColor redColor];           // animates :)
    myLayer.backGroundColor      = [[UIColor redColor] CGColor]; // animates :)
    
    myView.layer.backGroundColor = [[UIColor redColor] CGColor]; // animates :)
    [myView.layer addAnimation:myAnimation forKey:@"myKey"];     // animates :)
    

    您可以在上面看到独立层上的显式动画和隐式动画在动画 block 的外部和内部进行动画处理,但层支持 View 的隐式动画仅在动画 block 内部进行动画处理。

    关于ios - 在支持层的 View 上使用核心动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21226665/

    有关ios - 在支持层的 View 上使用核心动画的更多相关文章

    1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

      我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

    2. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

      我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

    3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

      类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

    4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

      很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

    5. ruby - 在 Ruby 中使用匿名模块 - 2

      假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

    6. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

      我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

    7. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    8. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

      我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

    9. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

      我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

    10. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

      我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

    随机推荐