自定义控件——属性动画进阶_wx_su的博客-程序员秘密

技术标签: 读书笔记  

1.PropertyValuesHolder与KeyFrame
在前一节我们了解了ofInt(),ofFloat(),ofObject()函数的用法。ValueAnimator和ObjectAnimator创建Animator实例除此之外还有ofProperValuesHolder()

//ValueAnimator
public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder ... 
values) 

//ObjectAnimator
public static ObjectAnimator ofPropertyValuesHolder(Object target, 
PropertyValuesHolder .. . values)

1.1 PropertyValuseHolder
PropertyValuesHolder类的含义就是,他其中保存了动画过程中所需要操作的属性和对应的值,在使用ofFloat(Object o,String propertyName,float … values)构造的动画,ofFloat()函数内部就是通过PropertyValuesHolder实例来保存动画状态的。在封装成PropertyValuesHolder实例之后,后期的各种操作就是以PropertyValuesHolder为主的。OnjectAnimator通过暴露PropertyValuesHolder的方法,向我们提供了一个口子,让我们可以通过PropertyValuesHolder来构造动画。
创建PropertyValuesHolder的实例函数如下:

public static PropertyValuesHolder ofFloat(String propertyName , float ... 
values) 
public static PropertyValuesHolder ofint (String propertyName , int .. va l ues ) 
public static PropertyValuesHolder ofObject(String propertyName , 
TypeEvaluator evaluator, Object ... values) 
public static PropertyValuesHolder ofKeyframe (String propertyName , Keyframe ... 
values)

在上面的ofInt(),ofFolat()中,propertyName表示ObjectAnimator需要操作的属性名。
values表示属性所对应的参数,为可边长参数。当只指定了参数时,ObjectAnimator会通过查找对应属性的getProperty()函数来获得初始值。与ObjectAnimator中的ofInt()相比较,只是少了一个target,在PropertyValuesHolder中的ofInt(),ofFloat()中创建的是PropertyValuesHolder对象,接下来是如何将PropertyValyesHolder实例设置到ObjectAnimator中。

1.1.1 ObjectAnimator.ofpropertyValuesHolder()
我们知道ObjectAnimator给我们提供了一个设置PropertyValuesHolder实例的入口

public static ObjectAnimator ofPropertyValuesHolder(Object target, 
PropertyValuesHolder .. . values)

target需要执行动画的控件
values可变长参数,可传入多个PropertyValuesHolder实例,由于每个PripertyValuesHolder实例都会针对一个属性执行动画操作,所以如果传入多个PropertyValuesHolder实例,则会对控件的多个属性同时执行动画操作。

1.1.2 PropertyValuesHolder之Object
ofObject()的构造函数

publc static PropertyValuesHolder ofObject (String propertyName , 
TypeEvaluator evaluator, Object . .. values)

propertyName——ObjectAnimator动画操作的属性名
evaluator——Evaluator实例
values——可变长参数,表示操作动画的属性的值

与ObjectAnimator.ofObject()函数的参数类似,只是少了一个target。

1.2 Keyframe
在看插值器,Evaluator时我们知道可以用来控制动画的速率,但是遇到较复杂的速率变化时,要涉及很复杂的数学知识,所以google提供了这样一个Keyframe类——关键帧,关键帧这个概念来源于动画,对于动画而言,一秒需要24帧图片,但是对于制作动画的人来说,并不是要把每一帧都画出来。比如,我们要让一只球在 30 秒内从(0,0 )点运动到(300,200)点在Flash 中,我们只需要定义两个关键帧, 在动画开始 定义1个关键帧,把球的位置设定在30秒后再定义一个关键帧,把球的位置设在(300,200)在动画开始时球位于(0,0)点,在 30 秒内 Adobe Flash就会自动填充,把球平滑移动到第二个关键帧的位置, 即(300,200) 点。
所以一个关键帧必须包含两个元素:时间点和位置
所以Keyframe的生成方式如下:

public static Keyframe ofFloat(float fraction , float value)

fraction表示当前的显示进度
value表示动画所在的数值位置
Keyframe ofFloat(0,0) 表示动画进度为0,动画所在数值位置为0;

1.2.1 PropertyValuesHolder是如何使用Keyframe对象的

public static PropertyValuesHolder ofKeyframe (String propertyName , Keyframe ... 
values)//属性名,keyfrane列表

KeyFrame的使用:
第一步 生成 Keyframe对象
第二步 利用 PropertyValuesHoIder.ofKeyframe() 函数生成 PropertyValuesHold对象
第三步 利用 ObjectAnimator.ofpropertyValuesHold () 函数生成对应Animator
示例:

Keyframe frameO = Keyframe . ofFloat (0f,0); 
Keyframe framel = Keyframe ofFloat(0.1f,-20f);
Keyframe frame2 = Keyframe ofFloat(1,0);
PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation ",
frame0 , framel , frame2 ); 
Animator ani mator = ObjectAnmator.ofPropertyValuesHolder(mimage frameHolder)
animator setDurat on(1000)
aηimator start();

1.2.2 ofFloat与ofInt
构造函数:

//ofFloat
public static Keyframe ofFloat(float fraction);
public static Keyframe ofFloat(float fraction,float value);

//ofInt
public static Keyframe ofInt(float fraction);
public static Keyframe ofInt(float fraction,int value);

两个函数的参数类型是一样的
fraction表示当前关键帧所在动画进度位置
value表示当前位置所对应的值

1.2.3 插值器
Keyframe允许我们在Keyframe动作期间设置插值器:
public void setInterpolator(TimeInteropolator interpolator)
如果给当前这个Keyframe设置了插值器,那么从上一个Keyframe到当前Keyframe就是使用了这个插值器来进行计算的。
在没有设置插值器的情况下一般时使用的LinearInterpolator线性插值器。

1.2.4 Keyframe之ofObject
ofObject的构造函数:

public static Keyframe ofObject(float fraction) 
public static Keyframe ofObect(float fraction ,float value)

它的使用方法和ofInt,ofFloat差不多
但是在使用ofObject函数来制作动画的时候,必须调用frameHolder.setEvaluator函数显式设置Evaluetor,因为系统根本无法知道动画的中间值Object真正是什么类型。

1.2.5 关键帧的使用情况:

  • 如果去掉第0帧,会以第一帧为起始位置
  • 去掉结束帧,会以最后一帧为结束帧
  • 只保留一个中间帧,会在动画开始的时候就直接崩溃

1.2.6 PropertyValuesHolder之其他函数
除了ofInt(),ofFloat(),ofObject(),ofKeyframe()函数之外还有很多函数

//设置动画的Evaluetor
public void setEvaluator(TypeEvaluator evaluator)
//设置ofFloat所对应的动画值列表
public void setFloatValues(float ...values)
//设置ofInt所对应的动画值列表
public void setIntValues(float ...values)
//设置ofKeyframe所对应的动画值列表
public void setKeyframeValues(float ...values)
//设置ofObject所对应的动画值列表
public void setObjectValues(float ...values)
//设置动画属性名
public void setPropertyName(String propertyName)

1.3 ViewPropertyAnimator
ViewPropertyAnimator为android控件提供了更加易懂,更加便捷的,更加面向对象的API,是我们操作控件更简单。
例如:
textView.animate().alpha(0f);//将textView变为透明
tv.animate().x(100).y(100);//将控件移动到(100,100)

  • animate——整个系统从调用View的这个animate()的新函数开始。这个函数会返回一个ViewPropertyAnimator对象,可以通过这个对象的函数来设置需要实现动画的属性。
  • 自动开始,不需要我们显式的调用start函数。
  • 流畅,ViewPropertyAnimator拥有一个非常流畅的接口,它允许将多个函数调用很自然的串在一起,并把多属性的动画写成一行代码。

1.3.1 常用函数
在这里插入图片描述
1.3.2 设置监听器
ViewPropertyAnimator并非派生自Animator,但它允许我们设置Animator.AnimatorListener监听器。用法如下:

tv.animate().scaleX(2).scaleY(1).setListener(new Aniamtor.AnimatorListener(){
		public void onAnimationStart(Animator animator){

		}
		public void onAnimationRepeat(Animator animator){

		}
		public void onAnimationEnd(Animator animator){

		}
		public void onAnimationCancel(Animator animator){

		}

});

1.4 为ViewGroup内的组件添加动画
ViewAnimator,ObjectAnimator,AnimatorSet都只可以针对一个控件作动画,而无法对ViewGroup内的组件添加动画。
为此android提供了4中方法来解决这个问题

  • LayoutAnimation标签与LayoutAniamtionController——专门针对listView添加入场动画,可以实现listView创建时对其中的每个item添加入场动画,而且动画是可以自定义的。但是在listview创建完成后,如果再添加数据,则新数据是不会有入场动画的。
  • gridLayoutAnimation标签与GridLayoutAnimationController——专门针对gridView添加入场动画,可以实现gridView创建时对其中的每个item添加入场动画,而且动画是可以自定义的。但是在gridview创建完成后,如果再添加数据,则新数据是不会有入场动画的。
  • android:animateLayoutChanges属性——在API11之后,android为了支持ViewGroup类控件,在添加和移除其中的控件时自动添加动画,提供的一个非常简单的属性,android:animateLayoutChanges=“true/false”,所有派生自ViewGroup的控件都具有这个属性,在xml中添加这个属性就可以实现在添加/删除其中控件时带有默认的动画,但是不能实现自定义动画
  • LayoutTransition——可以实现在ViewGroup动态添加或者删除其中的控件时指定动画。动画可以是自定义的。

由于前三种的缺陷,在这里主要理解第四种LayoutTransition
使用方法:
第一步:创建实例

LayoutTransition transition= new LayoutTransition();

第二步:创建动画并进行设置

ObjectAnimator animator=ObjectAnimator.ofFloat(null,"rotation",0f,90f,0f);
transition.setAnimator(LayoutTransition.DISAPPEARING,animOut);

第三步:将LayoutTransition设置到ViewGroup中

LinearLayout.setLayoutTransition(transition);

第二步和第三步用到的函数如下:

public void setLayoutTransition(LayoutTransition transition)

public void setAnimator(int transitionType,Animator animator)
//当transitionType为APPEARING——元素在容器中出现时所定义的动画
//DISAPPEARING——元素在容器中消失所定义的动画
//CHANGE_APPARING——由于容器中要显示一个新的元素,其他需要变化的元素所应用的动画
//CHANGE_DUSAPPEARING——当容器中某个元素消失时,其他需要变化的元素所应用的动画

1.5 开源动画库NineOldAndroids
NIneOldAndroids中是没有LayoutTransition类的,其他都有
1.5.1 NineOldAndroids中的ViewpropertyAnimator
在这里不同的主要是ViewPropertyAnimator中的animate方法,在官方API3.1以上animate是自动开始动画的,但是在NineOldAndroids中是静态使用的,需要有start启动。

1.5.2 NineOldAndroids中的ViewHelper
ViewHelper提供了一系列的静态set/get方法去操作View的各种属性。

public static float getAlpha(View view) 
public static void setAlpha (View view float alpha) 
public static void setPivotX(View view float pivotX) 
publc static float getP votX(View view) 
public static void setPivotY(View view, float pivotY) 
public static float getPivotY(View view) 
public static void setRotation(View riew float rotatio日)
public static float getRotation(View ew)
public static void setRotationX(View riew float rotat onX)
public static float getRotationX(View view )
....

ViewHelper与属性动画一样,也是通过改变控件的自由属性来改变控件的个项值。所以移动后的控件在新位置也是可以响应点击事件的。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_43847987/article/details/100553255

智能推荐

Arduino+ESP8266WIFI(2)——DHT11温湿度数据自动上传_五小郎的学习笔记的博客-程序员秘密

在模块测试之后,确保ESP8266能正常工作,开始与Arduino连接,将DHT11温湿度传感器检测的数据上传到监控平台。之前了解的平台有yeelink和thingspeak,原理应该都一样,我这里选用thingspeak,大家可以试试yeelink,欢迎提供学习分享。先把结果摆上欢迎访问:https://thingspeak.com/channels/296658 一、前期准备硬件:Ardui

SpringBoot | :异步开发之异步调用_weixin_34220179的博客-程序员秘密

前言除了异步请求,一般上我们用的比较多的应该是异步调用。通常在开发过程中,会遇到一个方法是和实际业务无关的,没有紧密性的。比如记录日志信息等业务。这个时候正常就是启一个新线程去做一些业务处理,让主线程异步的执行其他业务。所以,本章节重点说下在SpringBoot中如何进行异步调用及其相关知识和注意点。何为异步调用说异步调用前,我们说说它对应的同步调用。通常开发过程中,一般上我们都是同步调用,...

oracle视图传参_oracle视图传参数_李白列夫斯泰的博客-程序员秘密

1、对要传的参数写set、get方法create or replace package vm_param is function set_userid(user_ids varchar2) return varchar2; function get_userid return varchar2; function set_SHIFT_NAME(SHIFT_NAMES ...

GMS 包相关APK Crash 解决方案(持续更新中)_gms service crashed_程序员Android的博客-程序员秘密

GMS(GoogleMobile Service)包是出口国外手机中 Google 必须要预制,过 CTS 认证必须的。本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:多次刷机 开机向导过程中com.google.android.gms.ui Crash 解决方案 恢复出厂设置,com.google.android.gms.ui Crash 解...

骚操作之:Unity3D编辑器之监听脚本绑定事件与属性改变事件_unity 编辑器修改事件_AD_喵了个咪的博客-程序员秘密

在编辑模式下可能会用到, 比如我想做当绑定一个脚本后做点什么事情。。。 再比如我想当脚本序列化的数据发生改变做点什么事情等等。。举个典型的例子比如有些脚本需要美术 或者策划挂在场景的模型上, 那么这些模型有很多没用的的组件 比较Animation 或者 Collider 如果在这里监听的话, 当他们挂在脚本的时候就可以删除这些没用的了组件了。。把如下脚本在编辑模式下绑定在某个对象上即可。。Reset方法绑定脚本时会执行一次。以后每次点击”Reset”也会执行。OnValidate方法是脚本中..

递归法求二叉树的高度_ForeverMaba的博客-程序员秘密

递归法求二叉树的高度#include "BST.h"int max (int a ,int b){ if(a>=b) return a; else return b;}int hight( BSTNode<int,int *> *root ){ if( root == NULL ) retur...

随便推点

两种方法写tab导航条——1,原生js写tab导航条;2,jquery方法实现_tab导航怎么写_盛暖暖的博客-程序员秘密

如图所示,鼠标经过时,弹出子tab,上方横条切换到当前位置上。一、思路tab栏切换:用到排他思想,当鼠标经过时,设置所有的都隐藏,当前的显示;鼠标离开时,所有的都隐藏上方横条:需要获取距离左边的宽度,和当前索引下的宽度【注意】原生js的引入需要放到最下方,因为需要等整个dom加载完后,才加载jsjquery可以随处写二、步骤分解1.获取元素// 针对navline只需改变offsetleft和width即可// 1.获取元素var nav = document.querySelect

centOS7 重启后,连不上网(网卡不见了,ifcfg-ens33文件不存在)_Dr. 熊的博客-程序员秘密

问题ifconfig查询的时候,只有lo网卡,但是ifconfig -a查询的时候却有ens33网卡ls /etc/syconfig/network-scripts/查找所有网卡配置信息文件的时候,没有ifcfg-ens33网卡配置文件解决添加/etc/syconfig/network-scripts/ifcfg-ens33网卡配置文件,这是根据我的虚拟机信息的配置,具体ip地址IPA...

小小黑客从鼠标钩子开始,密码看看看_鼠标指针 密码查看方法_梳子不爱头发的博客-程序员秘密

引论什么是黑客,不同于骇客,黑客一词来源于“Hacker”,意思是劈,斩,对于黑客来说学会入侵和破解是提升自己和学习的过程,最重要的是编程能力,因为依赖大多数工具是体现不出自己水平的,所以这样说来很多安全软件公司的程序猿本身就是高明的黑客。 但是,骇客就不是这样了,骇客本身不需要学习如此多的语言,他们追求的是入侵的快感,盗取人家的私密,看现在网上大量艳照的流出,基本都是骇客干的好事,他们不一定会编

一文搞懂线程池原理——Executor框架详解_Kaiz‘s Blog的博客-程序员秘密

文章目录1 使用线程池的好处2 Executor 框架2.1 Executor 框架结构2.2 Executor 框架使用示意图2.3 Executor 框架成员2.3.1 Executor 与 ExecutorService2.3.2 Future接口2.3.3 Runnable接口和Callable接口2.3.4 Executors创建线程池3 ThreadPoolExecutor 详解3.1 线程池状态转换3.2 线程池处理流程3.2.1 execute()方法3.2.2 Worker线程管理3.2.

python打印菱形_python打印菱形_weixin_39578457的博客-程序员秘密

广告关闭腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元!usrbinpython # -*- coding:utf-8 -*- # 根据输入打印 rows = int(raw_input(please input number:)) #打印菱形上半部分 for i in range(rows): for j in range(rows -...

泪目!java项目源码免费下载_java源码下载_普通网友的博客-程序员秘密

前言今年我也33了,离传说中不好找工作的35岁又更近了。说没有焦虑是对自己撒谎,于是我采访了一些人,自己思考了下,写下了这篇文章,希望能有些共鸣。先看看大家的态度:色老力衰,不好忽悠,不能带头加班老油条,学不动,加班就是磨洋工关键还是贡献的价值。能不能给业务带来价值找背书基本逻辑就是,比你这个难得多的哥们都搞定了,你这点小事根本不再话下去bat镀镀金,捷径看看你的上司是咋过来的不知从何时起,很多企业将入职门槛限定在35岁以下,“35岁”已然成为职场老鸟的魔咒,而近年来有关**“程序员

推荐文章

热门文章

相关标签