在响应丝滑动画一篇文章中,分别介绍了作用于普通视图、绘制视图的绘制对象、和界面这三种对象的动画效果,但是都有一些使用的局限性。比如这些动画都只是以屏幕上绘制更新的方式绘制动画,并没有真实改变作用对象的实际位置或属性,这种问题在视图动画中尤为明显,在没有特别设置时,动画结束后的视图状态会还原到动画前,也就是说动画中及动画后的视图对象是没有保存动画中用到的一些属性的。这种情况就需要使用本文所介绍的属性动画了。
属性动画本质是对某个对象的属性提供一组变化更新的属性值,他的作用对象不仅可以是视图和界面,也可以是任何具有上述需求的对象类。在Android3.0 API 11开始的AndroidSDK版本中,定义了android.animation.Animator类作为抽象父类来描述属性动画的结构,并提供了android.animation.ValueAnimator作为只变化属性值的属性动画类、android.animation.ObjectAnimator可以变化属性值并更新到对象属性的属性动画类、和android.animation.AnimatorSet包含多个属性动画集合的属性动画类。
与普通动画类似,属性动画同样可以在资源文件中静态声明,也可以在代码中动态声明,但是由于其作用对象可以是任何对象,而且属性动画的优势在于为作用对象的属性提供一组变化的属性值,所以属性动画只能在需要绑定作用对象的代码位置动态使用。由于静态声明的属性动画可以针对多个对象使用,在开发过程中推荐使用静态声明+动态使用的方式。
ValueAnimator作为最核心的属性动画类,可以调用ValueAnimator.ofArgb(int... values)、ValueAnimator.ofFloat(float... values)、ValueAnimator.ofInt(int... values)、ValueAnimator.ofObject(TypeEvaluator evaluator, Object... values)系列静态方法,获取初始化后的实例化对象。其中的参数 values 是可变长参数,作为可变化属性值的范围区间。而参数 evaluator 是android.animation.TypeEvaluator估值器接口的实现类,用以计算估计属性值的具体变化数值的类。而AndroidSDK中已经定义了上述系列静态方法前三种类型对应的估值器子类,分别是android.animation.ArgbEvaluator、android.animation.FloatEvaluator、android.animation.IntEvaluator,除此之外还有计算二维坐标系的估值器android.animation.PointFEvaluator和计算矩形坐标的估值器android.animation.RectEvaluator。另外,在实际开发中针对作用对象要变化的属性值类型不同,也可以自定义实现TypeEvaluator接口的估值器。
这里提到的ArgbEvaluator是用以计算颜色的 ARGB 色值估值器,与Android系统定义的屏幕坐标类似,这里的 ARGB 色值也是一套系统颜色规范。在Java中int类型是用4个字节存储的,这4个字节按顺序从大端到小端,刚好分别表示Alpha(颜色值中的透明度),Red(颜色值中的红色值),Green(颜色值中的绿色值),Blue(颜色值中的蓝色值),每个字节的数值可以表示范围是[ 0x0, 0xFF ],所以用十六进制表示颜色值中的纯红色为 0xFFFF0000 ,纯黑色为 0xFF000000 ,纯白色为 0xFFFFFFFF ,而完全透明色为 0x00000000 到 0x00FFFFFF 之间的任一值。也可以借助android.graphics.Color类使用已经定义的颜色值和系统颜色规范的相关方法。
在创建ValueAnimator实例化对象后,
可以调用setDuration(long duration)设置完成一次动画效果的持续时间,单位为 ms 毫秒。
调用setRepeatCount(int value)设置完成一次动画效果后的重复次数,默认 value = ValueAnimator.INFINITE 为无限循环。
调用setRepeatMode(int value)设置在完成一次动画效果后重复时的动画效果,其 value 只能为
ValueAnimator.RESTART 表示从头开始重新完成一次一模一样的动画效果,
和ValueAnimator.REVERSE 表示从上次动画结尾开始完成一次倒放的动画效果。
调用 setInterpolator(TimeInterpolator value)设置动画效果的时间插值器。与上面的估值器定义结构类似,参数 value 是android.animation.TimeInterpolator插值器接口的实现类,用以确定每次更新动画效果的时间。同样的,AndroidSDK已经定义了一系列插值器,包括但不限于持续加速插值器android.view.animation.AccelerateInterpolator、持续减速插值器android.view.animation.DecelerateInterpolator、线性匀速插值器android.view.animation.LinearInterpolator等,同样在实际开发中针对动画效果展示时间进度,也可以自定义实现TimeInterpolator接口的插值器。
最终在需要启动当前属性动画的位置调用start()即开始播放当前动画效果,如果不想在调用属性动画的启动方法后立即执行相关动画效果,可以在启动方法之前调用setStartDelay(long startDelay)设置延时动画的延长时间,单位是 ms 毫秒。
ValueAnimator是根据TypeEvaluator估值器来更新属性值的,而更新的时间则是由TimeInterpolator插值器决定的,那么怎么才能拿到每次更新后的属性值呢?这里就可以用调用ValueAnimator对象的addUpdateListener(ValueAnimator.AnimatorUpdateListener listener)方法添加属性动画更新监听,在AnimatorUpdateListener类中重写onAnimationUpdate(ValueAnimator animation)方法,该方法中的参数animation即更新后的属性动画对象,通过调用animation.getAnimatedValue()来接收每次更新后的属性值,并可以将更新后的属性值赋值给需要属性动画的对象中。
也可以在资源文件中静态定义属性动画,在 res/animator 目录下,定义xml格式的属性动画资源文件,该资源文件内以<animator />为根标签,其中可以设置android:duration作为完成一次动画效果的持续时间等一系列属性,与代码中动态设置的相关方法类似。之后在代码使用位置加载该资源文件,通过调用AnimatorInflater.loadAnimator(Context context, int id)的静态方法,参数context作为调用位置所在的上下文环境,参数id则是要加载的属性动画类型的资源文件名。将得到Animator抽象类的返回结果,根据所加载资源文件中的根标签名判断,如果与<animator />一致,则可将返回的Animator抽象类直接转换为ValueAnimator类型的对象。
ObjectAnimator作为ValueAnimator的子类,定义和使用方式都有类似的地方,只是ObjectAnimator类中封装了属性动画的更新监听方法,因此只要绑定对象及其要变化的属性,在属性动画每次变化属性值时,都会主动将属性值更新到绑定对象的相关属性上。
因此在初始化实例对象时需要调用ofArgb(Object target, String propertyName, int... values)、ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)、ofInt(T target, Property<T, Integer> property, int... values)、ofObject(T target, Property<T, V> property, TypeConverter<PointF, V> converter, Path path)等系列静态方法。
其中参数 target 即为要绑定的动画效果作用对象;
参数 propertyName 是 target 对象中的某个属性,而且该属性必须要有符合驼峰命名规则的 get 和 set 方法;
参数 values 仍然作为可变化属性值的范围区间;
参数 path 作为android.graphics.Path类,则表示一段动画效果的执行路径,以此替换参数 values 表示的单一变化区间;
参数 property 作为android.util.Property抽象类,同样描述某种属性类型,以此替换String类型的参数 propertyName ;
参数 converter 作为android.animation.TypeConverter抽象类,与上文的参数 property 同时使用,当 property 中声明的属性类型与实际变化更新的属性值不一致时,使用参数 converter 所表示的强制类型转换方式。
在创建实例化对象后,ObjectAnimator有与ValueAnimator一致的setXXX()和getXXX()系列方法,另外还有setTarget(Object target)方法可以直接绑定要变化属性值的目标对象,同时有setPropertyName(String propertyName)和setProperty(Property property)两种调用方法,都能实现对目标对象中的目标属性的绑定。
最后仍然是在需要启动当前属性动画的位置调用start()开始播放当前动画效果。
在资源文件中静态定义时,同样在 res/animator 目录下,定义xml格式的属性动画资源文件,不过该资源文件内根标签为<objectAnimator />以标记关联对象的属性动画,其中的属性设置不仅与只变化属性值的ValueAnimator对应的<animator />标签中的属性一致,还可单独设置android:propertyName绑定属性名称。之后同样可以在代码中调用AnimatorInflater.loadAnimator(Context context, int id)静态方法加载当前属性动画资源文件,同样地,针对得到的Animator抽象类的返回结果,根据所加载资源文件中的根标签名判断,如果与<objectAnimator />一致,则可将返回的Animator抽象类直接转换为ObjectAnimator类型的对象。
SetAnimator是将一系列上述单独的属性动画组合起来的属性动画合集,其使用目的主要是为了讲不同的属性动画按照同一条时间线整理播放,因此其相关方法主要与其中子动画的播放顺序相关。
通过直接创建SetAnimator()构造方法可以获得SetAnimator实例化对象。
得到的对象调用playTogether(Animator... items)方法可以在同一段时间内播放添加的子动画,
调用playSequentially(Animator... items)方法可以将其中的子动画按照添加顺序播放,
而这两个系列方法中的可变长参数 items 即是要添加的系列子动画对象。
也可以将得到的对象调用play(Animator anim)方法,参数 anim 为添加的基本动画,返回android.animation.AnimatorSet.Builder类型,可以调用该类的before(Animator anim)方法设置针对基本动画之前播放的动画 anim 、调用该类的with(Animator anim)方法设置与基本动画同时播放的动画 anim 、调用该类的after(Animator anim)方法设置针对基本动画之后播放的动画 anim 、以及该类的after(long delay)方法设置在基本动画之后延时 delay 毫秒之后继续播放之后动画。
最后仍然是在需要启动当前属性动画的位置调用start()开始播放当前动画效果。
在资源文件中静态定义时,同样在 res/animator 目录下,定义xml格式的属性动画资源文件,在资源文件内根标签为<set></set>以标记为集合属性动画,该标签内可以设置属性android:ordering,其值只能为默认的together表示子动画同时执行,或者为sequentially表示子动画按顺序执行。在<set></set>标签内部,可以嵌入上述<animator />或<objectAnimator />两种属性动画标签。同样可以在代码中调用AnimatorInflater.loadAnimator(Context context, int id)静态方法加载当前属性动画资源文件,同样地,针对得到的Animator抽象类的返回结果,根据所加载资源文件中的根标签名判断,如果与<set></set>一致,则可将返回的Animator抽象类直接转换为AnimatorSet类型的对象。
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs
我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt