Pro Android学习笔记(一一四):2D动画(9):Property Animation(下)
2014-08-18 10:20
316 查看
文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying以及作者@恺风Wei。
public void viewPropertiesTest(View v){
//获取当前状态
float h = tv.getHeight();
float w = tv.getWidth();
float x = tv.getX();
float y = tv.getY();
//将view初始值。
tv.setX(w);
tv.setY(h);
tv.setAlpha(0.0f);
//从view中获取ViewPropertyAnimator的对象
ViewPropertyAnimator vpa = tv.animate();
//设置目标值
vpa.setDuration(5000);
vpa.x(x);
vpa.y(y);
vpa.alpha(1.0f);
vpa.setInterpolator(new AccelerateDecelerateInterpolator());
}
注意,和之前的方式不同,不需要通过start()来启动动画。当viewPropertiesTest()函数执行完,返回UI线程时,自动启动动画。
ObjectAnimator fadeout = ObjectAnimator.ofFloat(tv, "alpha", 0.0f);
//将alpha从当前值变为0(看不见),ofFloat()表明这是对tv对象(参数1)的alpha属性(参数2)进行的浮点类型数值的变化,从当前值变化至目标值(参数3)。哪些可以作为属性,需要具备setXXX()方法,则具备XXX属性,本例Textview对象具有public方法 view.setAlpha(float f)方法,故具有属性alpha。初始值从view.getAlpha()中获取。如果带有4个参数,例如 ofFloat(tv,"alpha",1.0f,0.0f),则第三个参数标识from的数值,第4个参数标识to的数值,即从alpha属性从1.0
变为0.0。
fadeout.setDuration(5000);
fadeout.start();
下面,我们将使用PointF(坐标类)来作为属性的值。由于目标的TextView并没有setPoint()和getPoint()的函数,我们需要通过自定义的MyAnimatorView类来实现。我们给出了“point”这个属性的初始值和最终值,但是在动画过程中的中间值如何,需要通过TypeEvaluator的evaluate()来给出,然后通过setPoint()设置给动画对象。
public void typeEvaluatorTest(View v){
//获取当前状态
float h = tv.getHeight();
float w = tv.getWidth();
float x = tv.getX();
float y = tv.getY();
// 获取动画变化属性的初始值和最终值
PointF startPoint = new PointF(w, h);
PointF endPoint = new PointF(x,y);
// 步骤1 :提供自定义属性“point”的动画对象
MyAnimatorView mav = new MyAnimatorView(tv);
// 步骤2 :通过ObjectAnimator的ofObject()来设置动画类型。参数1为动画对象;参数2对属性名称,动画对象应提供setXXX()的方法;参数3为动画过程中的中间值设定;参数4/5是初始值和最终值,如果只有参数4,则参数4位最种植,初始值由动画对象的getXXX()提供。下面分别给出了不带初始值和带有初始值的两种情况。
//ObjectAnimator tea = ObjectAnimator.ofObject(mav, "point", new MyPointEvaluator(), endPoint);
ObjectAnimator tea = ObjectAnimator.ofObject(mav, "point", new MyPointEvaluator(), startPoint,endPoint);
tea.setDuration(5000);
Log.d("WEI","------------------------------");
tea.start();
}
下面是使用TypeEvaluator来提供中间的组合属性,本例为PointF,代码片段如下:
public class MyPointEvaluator implements TypeEvaluator<PointF>{
@Override
// 实现TypeEvaluator接口的evaluate()方式,fraction是动画的进度,从0.0到1.0,根据进度,初始值和最终值,给出动画过程的中间值。
public PointF evaluate(float fraction, PointF startValue, PointF endValue){
Log.d("WEI","MyPointEvaluator : evaluate " + fraction);
return new PointF(startValue.x + fraction * (endValue.x - startValue.x),
startValue.y + fraction * (endValue.y - startValue.y));
}
}
由于TextView不提供setPoint()的方法,不能直接作为动画对象,需要进行封装,代码片段如下:
public class MyAnimatorView{
private View myView = null;
private MyAnimatorView(View v){
myView = v;
}
// 如果没有初始值,同getPoint()获取,本例设置为右下角
public PointF getPoint(){
Log.d("WEI","MyAnimatorView : getPoint()");
return new PointF(myView.getWidth(),myView.getHeight());
}
// 通过setPoint()来设置中间值
public void setPoint(PointF p){
Log.d("WEI","MyAnimatorView : setPoint (" + p.x + "," + p.y + ")");
myView.setX(p.x);
myView.setY(p.y);
}
}
下图是没有设置初始值和设置初始值的debug跟踪情况:
在小例子中,属性的组合使用了PointF的坐标类型,我们也可以加入其它的属性,自定义属性的组合。
public void keyFrameTest(View v){
//获取当前状态
float w = tv.getWidth();
float x = tv.getX();
// 为某个属性(本例子为alpha)设定特定时间的值。参数1为fraction,表示进度;参数2为具体数值,下面表示在进度20%时,该值为0.8,在50%时为0.2,在80%是为0.8,在100%(即最后)为1.0。
Keyframe kf0 = Keyframe.ofFloat(0.2f, 0.8f);
Keyframe kf1 = Keyframe.ofFloat(0.5f, 0.2f);
Keyframe kf2 = Keyframe.ofFloat(0.8f, 0.8f);
Keyframe kf3 = Keyframe.ofFloat(1.0f, 1.0f);
//通过PropertyValuesHolder来关联keyframe和属性。此外,我们还设置一个从x轴从右到左的移动
PropertyValuesHolder pvAlpha = PropertyValuesHolder.ofKeyframe("alpha", kf0,kf1,kf2,kf3);
PropertyValuesHolder pvX = PropertyValuesHolder.ofFloat("x", w, x);
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(tv, pvAlpha,pvX);
anim.setDuration(5000);
anim.start();
}
1、增加一个View(view出现,LayoutTransition.APPEARING)
2、因增加view,而改变现实的其他view(LayoutTransition.CHANGE_APPEARING)
3、删除一个View(LayoutTransition.DISAPPEARING)
4、因删除某个View,而改变现实的其他view(LayoutTransition.CHANGE_DISAPPEARING)
小例子以第一种情况,即在Layout中增加一个view,view出现时具备某种动画效果。首选,需要对Layout中通过LayoutTransition对上述view变化进行设定,可以放在activity初始化阶段:
protected void onCreate(Bundle savedInstanceState) {
… …
myLayout = (LinearLayout)findViewById(R.id.my_layout);
//【步骤1】:将LayoutTransittion关联与某个view group中,本例为LinearLayout
LayoutTransition lt = new LayoutTransition();
myLayout.setLayoutTransition(lt);
//【步骤2】:针对4种情况情况进行动画设置,本例子讲针对添加view的情况,即LayoutTransition.APPREAING
//(2.1)设置动画ObjectAnimator,其中对象目标为何不重要,因为会通过LayoutTransition对象关联到layout,可设置为null。LayoutTransition的动画是有缺省值的,通过LogCat显示为300ms,如果我们设定的动画时间超过该值,是不其作用的,这种情况,可以通过设置LayoutTransition的动画时间来解决,例如本例可设置lt.setDuration(5000),提供一个慢速的动画效果。
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,0f);
animIn.setDuration(lt.getDuration(LayoutTransition.APPEARING));
Log.d("WEI","" + lt.getDuration(LayoutTransition.APPEARING));
//(2.2)将动画加在LayoutTransition上,并指出属于那种情况下的动画
lt.setAnimator(LayoutTransition.APPEARING, animIn);
//(2.3)可以监听动画的执行情况
animIn.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
@Override //获取进行动画的view的例子
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
Log.d("WEI",view.toString());
}
@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
}
我们也可以设置其他的情况的动画,例如删除
Keyframe kf0 = Keyframe.ofFloat(0.2f, 0.8f);
Keyframe kf1 = Keyframe.ofFloat(0.5f, 0.5f);
Keyframe kf2 = Keyframe.ofFloat(1.0f, 0.0f);
PropertyValuesHolder pvh = PropertyValuesHolder.ofKeyframe( "alpha", kf0, kf1, kf2);
ObjectAnimator animOut = ObjectAnimator.ofPropertyValuesHolder(myLayout, pvh);
animOut.setDuration(lt.getDuration(LayoutTransition.DISAPPEARING));
lt.setAnimator(LayoutTransition.DISAPPEARING, animOut);
如果我们要记住某个时刻动画设置,以便后来恢复,可以使用:
Animator defaultAppearAnimator = lt.getAnimator(APPEARING);
在设置了LayoutTransition后,我们进行添加view的测试,如下:
TextView testView1 = new TextView(this);
testView1.setText("测试Layout Transition。Hello, World! ");
myLayout.addView(testView1);
通过LayoutTranistion将动画加诸在每个view中,animator会复制给每个view。如果这些view有onClick的处理,在进行动画的过程中,如果进行点击,其结果不可预测,因此一般动画设定时间不要过长。
小例子代码在:Pro Android学习:2D动画小例子
相关链接:我的Android开发相关文章
ViewPropertyAnimator
如果我们动画的对象是view,Android SDK通过ViewProperyAnimator提供一种更为优化的实现方式,同样一次性设置多个值的变化。小例子片段如下:public void viewPropertiesTest(View v){
//获取当前状态
float h = tv.getHeight();
float w = tv.getWidth();
float x = tv.getX();
float y = tv.getY();
//将view初始值。
tv.setX(w);
tv.setY(h);
tv.setAlpha(0.0f);
//从view中获取ViewPropertyAnimator的对象
ViewPropertyAnimator vpa = tv.animate();
//设置目标值
vpa.setDuration(5000);
vpa.x(x);
vpa.y(y);
vpa.alpha(1.0f);
vpa.setInterpolator(new AccelerateDecelerateInterpolator());
}
注意,和之前的方式不同,不需要通过start()来启动动画。当viewPropertiesTest()函数执行完,返回UI线程时,自动启动动画。
TypeEvaluator
回眸ObjectAnimator最初的小例子,通过onFloat()或者onInt()对某个属性进行设置。如果这个属性不是简单的某个value,而是对象,就需要使用onObject()来进行设置。这个对象属性可以是我们自定义的。我们回头看看当初小例子中的部分代码及解释:ObjectAnimator fadeout = ObjectAnimator.ofFloat(tv, "alpha", 0.0f);
//将alpha从当前值变为0(看不见),ofFloat()表明这是对tv对象(参数1)的alpha属性(参数2)进行的浮点类型数值的变化,从当前值变化至目标值(参数3)。哪些可以作为属性,需要具备setXXX()方法,则具备XXX属性,本例Textview对象具有public方法 view.setAlpha(float f)方法,故具有属性alpha。初始值从view.getAlpha()中获取。如果带有4个参数,例如 ofFloat(tv,"alpha",1.0f,0.0f),则第三个参数标识from的数值,第4个参数标识to的数值,即从alpha属性从1.0
变为0.0。
fadeout.setDuration(5000);
fadeout.start();
下面,我们将使用PointF(坐标类)来作为属性的值。由于目标的TextView并没有setPoint()和getPoint()的函数,我们需要通过自定义的MyAnimatorView类来实现。我们给出了“point”这个属性的初始值和最终值,但是在动画过程中的中间值如何,需要通过TypeEvaluator的evaluate()来给出,然后通过setPoint()设置给动画对象。
public void typeEvaluatorTest(View v){
//获取当前状态
float h = tv.getHeight();
float w = tv.getWidth();
float x = tv.getX();
float y = tv.getY();
// 获取动画变化属性的初始值和最终值
PointF startPoint = new PointF(w, h);
PointF endPoint = new PointF(x,y);
// 步骤1 :提供自定义属性“point”的动画对象
MyAnimatorView mav = new MyAnimatorView(tv);
// 步骤2 :通过ObjectAnimator的ofObject()来设置动画类型。参数1为动画对象;参数2对属性名称,动画对象应提供setXXX()的方法;参数3为动画过程中的中间值设定;参数4/5是初始值和最终值,如果只有参数4,则参数4位最种植,初始值由动画对象的getXXX()提供。下面分别给出了不带初始值和带有初始值的两种情况。
//ObjectAnimator tea = ObjectAnimator.ofObject(mav, "point", new MyPointEvaluator(), endPoint);
ObjectAnimator tea = ObjectAnimator.ofObject(mav, "point", new MyPointEvaluator(), startPoint,endPoint);
tea.setDuration(5000);
Log.d("WEI","------------------------------");
tea.start();
}
下面是使用TypeEvaluator来提供中间的组合属性,本例为PointF,代码片段如下:
public class MyPointEvaluator implements TypeEvaluator<PointF>{
@Override
// 实现TypeEvaluator接口的evaluate()方式,fraction是动画的进度,从0.0到1.0,根据进度,初始值和最终值,给出动画过程的中间值。
public PointF evaluate(float fraction, PointF startValue, PointF endValue){
Log.d("WEI","MyPointEvaluator : evaluate " + fraction);
return new PointF(startValue.x + fraction * (endValue.x - startValue.x),
startValue.y + fraction * (endValue.y - startValue.y));
}
}
由于TextView不提供setPoint()的方法,不能直接作为动画对象,需要进行封装,代码片段如下:
public class MyAnimatorView{
private View myView = null;
private MyAnimatorView(View v){
myView = v;
}
// 如果没有初始值,同getPoint()获取,本例设置为右下角
public PointF getPoint(){
Log.d("WEI","MyAnimatorView : getPoint()");
return new PointF(myView.getWidth(),myView.getHeight());
}
// 通过setPoint()来设置中间值
public void setPoint(PointF p){
Log.d("WEI","MyAnimatorView : setPoint (" + p.x + "," + p.y + ")");
myView.setX(p.x);
myView.setY(p.y);
}
}
下图是没有设置初始值和设置初始值的debug跟踪情况:
在小例子中,属性的组合使用了PointF的坐标类型,我们也可以加入其它的属性,自定义属性的组合。
Keyframe
通过Keyframe,我们可以设定某个时刻,某属性的值是多少。下面的小例子,通过对alpha的设定,实现变淡在变浓的效果。public void keyFrameTest(View v){
//获取当前状态
float w = tv.getWidth();
float x = tv.getX();
// 为某个属性(本例子为alpha)设定特定时间的值。参数1为fraction,表示进度;参数2为具体数值,下面表示在进度20%时,该值为0.8,在50%时为0.2,在80%是为0.8,在100%(即最后)为1.0。
Keyframe kf0 = Keyframe.ofFloat(0.2f, 0.8f);
Keyframe kf1 = Keyframe.ofFloat(0.5f, 0.2f);
Keyframe kf2 = Keyframe.ofFloat(0.8f, 0.8f);
Keyframe kf3 = Keyframe.ofFloat(1.0f, 1.0f);
//通过PropertyValuesHolder来关联keyframe和属性。此外,我们还设置一个从x轴从右到左的移动
PropertyValuesHolder pvAlpha = PropertyValuesHolder.ofKeyframe("alpha", kf0,kf1,kf2,kf3);
PropertyValuesHolder pvX = PropertyValuesHolder.ofFloat("x", w, x);
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(tv, pvAlpha,pvX);
anim.setDuration(5000);
anim.start();
}
LayoutTransition
通过LayoutTransition可以对view group中的各个view进行动画处理,这些动画处理包括四种情况:1、增加一个View(view出现,LayoutTransition.APPEARING)
2、因增加view,而改变现实的其他view(LayoutTransition.CHANGE_APPEARING)
3、删除一个View(LayoutTransition.DISAPPEARING)
4、因删除某个View,而改变现实的其他view(LayoutTransition.CHANGE_DISAPPEARING)
小例子以第一种情况,即在Layout中增加一个view,view出现时具备某种动画效果。首选,需要对Layout中通过LayoutTransition对上述view变化进行设定,可以放在activity初始化阶段:
protected void onCreate(Bundle savedInstanceState) {
… …
myLayout = (LinearLayout)findViewById(R.id.my_layout);
//【步骤1】:将LayoutTransittion关联与某个view group中,本例为LinearLayout
LayoutTransition lt = new LayoutTransition();
myLayout.setLayoutTransition(lt);
//【步骤2】:针对4种情况情况进行动画设置,本例子讲针对添加view的情况,即LayoutTransition.APPREAING
//(2.1)设置动画ObjectAnimator,其中对象目标为何不重要,因为会通过LayoutTransition对象关联到layout,可设置为null。LayoutTransition的动画是有缺省值的,通过LogCat显示为300ms,如果我们设定的动画时间超过该值,是不其作用的,这种情况,可以通过设置LayoutTransition的动画时间来解决,例如本例可设置lt.setDuration(5000),提供一个慢速的动画效果。
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f,0f);
animIn.setDuration(lt.getDuration(LayoutTransition.APPEARING));
Log.d("WEI","" + lt.getDuration(LayoutTransition.APPEARING));
//(2.2)将动画加在LayoutTransition上,并指出属于那种情况下的动画
lt.setAnimator(LayoutTransition.APPEARING, animIn);
//(2.3)可以监听动画的执行情况
animIn.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
@Override //获取进行动画的view的例子
public void onAnimationEnd(Animator animation) {
View view = (View) ((ObjectAnimator) animation).getTarget();
Log.d("WEI",view.toString());
}
@Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
}
我们也可以设置其他的情况的动画,例如删除
Keyframe kf0 = Keyframe.ofFloat(0.2f, 0.8f);
Keyframe kf1 = Keyframe.ofFloat(0.5f, 0.5f);
Keyframe kf2 = Keyframe.ofFloat(1.0f, 0.0f);
PropertyValuesHolder pvh = PropertyValuesHolder.ofKeyframe( "alpha", kf0, kf1, kf2);
ObjectAnimator animOut = ObjectAnimator.ofPropertyValuesHolder(myLayout, pvh);
animOut.setDuration(lt.getDuration(LayoutTransition.DISAPPEARING));
lt.setAnimator(LayoutTransition.DISAPPEARING, animOut);
如果我们要记住某个时刻动画设置,以便后来恢复,可以使用:
Animator defaultAppearAnimator = lt.getAnimator(APPEARING);
在设置了LayoutTransition后,我们进行添加view的测试,如下:
TextView testView1 = new TextView(this);
testView1.setText("测试Layout Transition。Hello, World! ");
myLayout.addView(testView1);
通过LayoutTranistion将动画加诸在每个view中,animator会复制给每个view。如果这些view有onClick的处理,在进行动画的过程中,如果进行点击,其结果不可预测,因此一般动画设定时间不要过长。
小例子代码在:Pro Android学习:2D动画小例子
相关链接:我的Android开发相关文章
相关文章推荐
- Pro Android学习笔记(一一四):2D动画(9):Property Animation(下)
- Pro Android学习笔记(一一十):2D动画(5):Camera
- Pro Android学习笔记(一一一):2D动画(6):AnimationListener
- Pro Android学习笔记(一零七):2D动画(2):layout渐变动画
- Pro Android学习笔记(一零八):2D动画(3):view动画的小例子
- Pro Android学习笔记(一零九):2D动画(4):view的Matrix
- Pro Android学习笔记(一零六):2D动画(1):frame by frame
- Pro Android学习笔记(一一二):2D动画(7):Property Animation(上)
- Pro Android学习笔记(一一三):2D动画(8):Property Animation(中)
- Unity3D 2D动画插件EasyMotion2D (之十一)SpriteAnimationClip Editor
- android学习笔记---54_tween动画的实现
- FCPX插件:自定义路径元素跟踪动画 PROKEYFRAME for Mac 附prokeyframe 使用教程
- 【转】Pro Android学习笔记(二):开发环境:基础概念、连接真实设备、生命周期
- FCPX插件:30个自动动画标题效果 prointro blend for Mac 破解版
- 【转】Pro Android学习笔记(十五):用户界面和控制(3):Button控件
- 【转】 Pro Android学习笔记(三一):Menu(2):扩展、图片、子菜单
- 【转】Pro Android学习笔记(四六):Dialog(3):对话框弹对话框
- 【转】 Pro Android学习笔记(六二):Preferences(6):header
- 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件
- 【转】 Pro Android学习笔记(九三):AsyncTask(2):小例子