您的位置:首页 > 移动开发 > Android开发

Android-Property_Animation介绍及基本实现(属性动画)

2015-08-29 20:55 585 查看

属性动画

补间动画,只是一个动画效果,组件其实还在原来的位置上,xy没有改变

位移:

第一个参数target指定要显示动画的组件

第二个参数propertyName指定要改变组件的哪个属性

第三个参数values是可变参数,就是赋予属性的新的值

传入0,代表x起始坐标:当前x + 0

传入100,代表x终点坐标:当前x + 100
//具有get、set方法的成员变量就称为属性
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "translationX", 0, 100) ;


缩放:

第三个参数指定缩放的比例

0.1是从原本高度的十分之一开始

2是到原本高度的2倍结束
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "scaleY", 0.1f, 2);


透明:

透明度,0是完全透明,1是完全不透明
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "alpha", 0.1f, 1);


旋转

rotation指定是顺时针旋转

20是起始角度

270是结束角度
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "rotation", 20, 270);


属性指定为rotationX是竖直翻转

属性指定为rotationY是水平翻转
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "rotationY", 20, 180);


可变参数

第三个参数可变参数可以传入多个参数,可以实现往回位移(旋转、缩放、透明)
ObjectAnimator oa = ObjectAnimator.ofFloat(bt, "translationX", 0, 70, 30, 100) ;


所有动画一起飞

//创建动画师集合
AnimatorSet set = new AnimatorSet();
//设置要播放动画的组件
set.setTarget(bt);
//所有动画有先后顺序的播放
//set.playSequentially(oa, oa2, oa3, oa4);
//所有动画一起播放
set.playTogether(oa, oa2, oa3, oa4);
set.start();


属性动画,这个是在Android 3.0中才引进的,它可以直接更改我们对象的属性。在上面提到的Tween Animation中,只是更改View的绘画效果而View的真实属性是不改变的。假设你用Tween动画将一个Button从左边移到右边,无论你怎么点击移动后的Button,他都没有反应。而当你点击移动前Button的位置时才有反应,因为Button的位置属性木有改变。而Property Animation则可以直接改变View对象的属性值,这样可以让我们少做一些处理工作,提高效率与代码的可读性。

(1)ValueAnimator:包含Property Animation动画的所有核心功能,如动画时间,开始、结束属性值,相应时间属性值计算方法等。应用ValueAnimator有两个步骤

1计算属性值。

2根据属性值执行相应的动作,如改变对象的某一属性。

我们的主是第二步,需要实现ValueAnimator.onUpdateListener接口,这个接口只有一个函数onAnimationUpdate(),将要改变View对象属性的事情在该接口中do。
<span style="font-family:KaiTi_GB2312;font-size:18px;">animation.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//do your work
}
});  </span>


(2)ObjectAnimator:继承自ValueAnimator,要指定一个对象及该对象的一个属性,当属性值计算完成时自动设置为该对象的相应属性,即完成了Property Animation的全部两步操作。实际应用中一般都会用ObjectAnimator来改变某一对象的某一属性,但用ObjectAnimator有一定的限制,要想使用ObjectAnimator,应该满足以下条件:

1.对象应该有一个setter函数:set<PropertyName>(驼峰命名法)

2如下面的例子,像ofFloat之类的工场方法,第一个参数为对象名,第二个为属性名,后面的参数为可变参数,如果values…参数只设置了一个值的话,那么会假定为目的值,属性值的变化范围为当前值到目的值,为了获得当前值,该对象要有相应属性的getter方法:get<PropertyName>

3如果有getter方法,其应返回值类型应与相应的setter方法的参数类型一致。
<span style="font-family:KaiTi_GB2312;font-size:18px;">ObjectAnimator oa=ObjectAnimator.ofFloat(tv, "alpha", 0f, 1f);
oa.setDuration(3000);
oa.start();  </span>


如果不满足上面的条件,我们只能乖乖的使用ValueAnimator来创建动画。

 

(3)Animator.AnimatorListener:可以为Animator设置动画监听,需要重写下面四个方法。
<span style="font-family:KaiTi_GB2312;font-size:18px;">onAnimationStart()
onAnimationEnd()
onAnimationRepeat()
onAnimationCancel()  </span>


这里我们也可以实现AnimatorListenerAdapter,他的好处是可以只用定义想监听的事件而不用实现每个函数却只定义一空函数体。如下:

<span style="font-family:KaiTi_GB2312;font-size:18px;">anim.addListener(new AnimatorListenerAdapter() {
public void on AnimationEnd(Animator animation){
//do your work
}
}); </span>

(4)AnimationSet:可以组合多个动画共同工作

<span style="font-family:KaiTi_GB2312;font-size:18px;">AnimatorSet bouncer = new AnimatorSet();
bouncer.play(anim1).before(anim2);
bouncer.play(anim2).with(anim3);
bouncer.play(anim2).with(anim4)
bouncer.play(anim5).after(amin2);
animatorSet.start(); </span>

上面的代码意思是: 首先播放anim1;同时播放anim2,anim3,anim4;最后播放anim5。

 

(5)TimeInterplator:与Tween中的interpolator类似。有以下几种

AccelerateInterpolator          加速,开始时慢中间加速

DecelerateInterpolator          减速,开始时快然后减速

AccelerateDecelerateInterolator      先加速后减速,开始结束时慢,中间加速

AnticipateInterpolator         反向 ,先向相反方向改变一段再加速播放

AnticipateOvershootInterpolator     反向加回弹,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值

BounceInterpolator         跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100

CycleIinterpolator         循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2 * mCycles * Math.PI * input)

LinearInterpolator         线性,线性均匀改变

OvershottInterpolator        回弹,最后超出目的值然后缓慢改变到目的值

TimeInterpolator          一个接口,允许你自定义interpolator,以上几个都是实现了这个接口

 

(6)Keyframes:可以让我们定义除了开始和结束以外的关键帧。KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,如下:
<span style="font-family:KaiTi_GB2312;font-size:18px;">Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf4 = Keyframe.ofInt(0.75f, 100);
Keyframe kf3 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf4, kf3);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(btn, pvhRotation);  </span>


上述代码的意思是:设置btn对象的width属性值使其:开始时 Width=400,动画开始1/4时 Width=200,动画开始1/2时 Width=400,动画开始3/4时 Width=100,动画结束时 Width=500。

 

(7)ViewPropertyAnimator:对一个View同时改变多种属性,非常推荐用这种。该类对多属性动画进行了优化,会合并一些invalidate()来减少刷新视图。而且使用起来非常简便,但是要求API LEVEL 12,即Android 3.1以上。仅需要一行代码即可完成水平、竖直移动
<span style="font-family:KaiTi_GB2312;font-size:18px;">myView.animate().translationX(50f). translationY(100f);  </span>


(8)常需要改变的一些属性:

translationX,translationY: View相对于原始位置的偏移量

rotation,rotationX,rotationY: 旋转,rotation用于2D旋转角度,3D中用到后两个

scaleX,scaleY: 缩放比

x,y: View的最终坐标,是View的left,top位置加上translationX,translationY

alpha: 透明度
效果图:



代码实例:

在app\src\main\res\目录下创建animator文件夹,在animator目录下创建objanimator.xml



objanimator.xml

<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:repeatCount="1"
android:repeatMode="reverse"
android:valueFrom="-100"
android:valueTo="100"></objectAnimator>
</set></span>activity_main.xml
<span style="font-family:KaiTi_GB2312;font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher"
android:layout_centerInParent="true"
/>
<Button
android:layout_centerHorizontal="true"
android:layout_above="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="xml定义的属性动画"
android:onClick="xml"
/>
<LinearLayout
android:id="@+id/ll"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="平移"
android:onClick="translate"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="缩放"
android:onClick="scale"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="透明"
android:onClick="alpha"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="旋转"
android:onClick="rotate"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="一起飞"
android:onClick="fly"
/>
</LinearLayout>

</RelativeLayout>
</span>MainActivity.java
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.example.yu_longji.android20;

import android.animation.Animator;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

public class MainActivity extends Activity {

private ImageView iv;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
iv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "点不到我", Toast.LENGTH_SHORT).show();
}
});
}

//平移
public void translate(View view) {
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX", 10, 100, 20, 200);
oa.setDuration(2000);
oa.setRepeatMode(ObjectAnimator.REVERSE);
oa.setRepeatCount(1);
oa.start();
}

//缩放
public void scale(View v) {
//scaleX缩放
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleX", 0.5f, 1.6f, 1.2f, 3);
oa.setDuration(2000);
oa.start();
}

//透明
public void alpha(View v) {
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0, 0.6f, 0.2f, 1);
oa.setDuration(2000);
oa.start();
}

//旋转
public void rotate(View v) {
ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationY", 0, 180, 90, 360);
oa.setDuration(2000);
oa.setRepeatCount(1);
oa.setRepeatMode(ValueAnimator.REVERSE);
oa.start();
}

//平移、缩放、透明、旋转一起进行
public void fly(View v) {
AnimatorSet set = new AnimatorSet();

ObjectAnimator oa1 = ObjectAnimator.ofFloat(iv, "translationX", 10, 70, 20, 100);
oa1.setDuration(2000);
oa1.setRepeatCount(1);
oa1.setRepeatMode(ValueAnimator.REVERSE);

ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "translationY", 10, 70, 20, 100);
oa2.setDuration(2000);
oa2.setRepeatCount(1);
oa2.setRepeatMode(ValueAnimator.REVERSE);

ObjectAnimator oa3 = ObjectAnimator.ofFloat(iv, "scaleX", 1, 1.6f, 1.2f, 2);
oa3.setDuration(2000);
oa3.setRepeatCount(1);
oa3.setRepeatMode(ValueAnimator.REVERSE);

ObjectAnimator oa4 = ObjectAnimator.ofFloat(iv, "rotation", 0, 180, 90, 360);
oa4.setDuration(2000);
oa4.setRepeatCount(1);
oa4.setRepeatMode(ValueAnimator.REVERSE);

//设置挨个执行
// set.playSequentially(oa1, oa2, oa3, oa4);
//设置一起执行
set.playTogether(oa1, oa2, oa3, oa4);
set.start();
}

public void xml(View v) {
Animator at = AnimatorInflater.loadAnimator(this, R.animator.objanimator);
//设置作用于哪个组件
at.setTarget(iv);
at.start();
}
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息