Tween动画,就是对场景里的对象不断的进行图像变化来产生动画效果(旋转、平移、放缩和渐变)
使用动画来进行旋转、平移、放缩和渐变比通过手动重新绘制Canvas来达到相似效果要消耗更少的资源,实现更简单
1.创建补间动画
AlphaAnimation
java:
Animation alphaAnimation = new AlphaAnimation(0.1f, 1.0f);
alphaAnimation.setDuration(3000);
this.startAnimation(alphaAnimation);
其中AlphaAnimation类第一个参数fromAlpha表示动画起始时的透明度, 第二个参数toAlpha表示动画结束时的透明度。
setDuration用来设置动画持续时间。
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="0.1"
android:toAlpha="1.0"
android:duration="2000"
/>
</set>
RotateAnimation
java:
Animation rotateAnimation = new RotateAnimation(0f, 360f);
rotateAnimation.setDuration(1000);
this.startAnimation(rotateAnimation);
其中RotateAnimation类第一个参数fromDegrees表示动画起始时的角度, 第二个参数toDegrees表示动画结束时的角度。
另外还可以设置伸缩模式pivotXType、pivotYType, 伸缩动画相对于x,y 坐标的开始位置pivotXValue、pivotYValue等。
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="500"
/>
</set>
ScaleAnimation
java:
Animation scaleAnimation = new ScaleAnimation(0.1f, 1.0f,0.1f,1.0f);
scaleAnimation.setDuration(500);
this.startAnimation(scaleAnimation);
第一个参数fromX ,第二个参数toX:分别是动画起始、结束时X坐标上的伸缩尺寸。
第三个参数fromY ,第四个参数toY:分别是动画起始、结束时Y坐标上的伸缩尺寸。
另外还可以设置伸缩模式pivotXType、pivotYType, 伸缩动画相对于x,y 坐标的开始位置pivotXValue、pivotYValue等。
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:fillAfter="false"
android:duration="500"
android:startOffset="700"
android:repeatCount="10"
/>
</set>
TranslateAnimation
java:
Animation translateAnimation = new TranslateAnimation(0.1f, 100.0f,0.1f,100.0f);
translateAnimation.setDuration(1000);
this.startAnimation(translateAnimation);
第一个参数fromXDelta ,第二个参数toXDelta:分别是动画起始、结束时X坐标。
第三个参数fromYDelta ,第四个参数toYDelta:分别是动画起始、结束时Y坐标。
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="10"
android:toXDelta="100"
android:fromYDelta="10"
android:toYDelta="100"
/>
</set>
AnimationSet
java:
translateAnimation = new TranslateAnimation(0.1f, 100.0f,0.1f,100.0f);
alphaAnimation = new AlphaAnimation(0.1f, 1.0f);
AnimationSet set = new AnimationSet(true);
set.addAnimation(translateAnimation);
set.addAnimation(alphaAnimation);
set.setDuration(1000);
this.startAnimation(set);
xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:duration="300"
android:fromYDelta="100"
android:toYDelta="0" />
透明度渐变
<alpha
android:duration="300"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<scale
android:duration="300"
android:fillAfter="false"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" >
</scale>
</set>
2.使用补间动画
动画资源存放在项目的res/anim文件夹下
如何来使用这些xml文件呢?其实也很简单,此时需要用到AnimationUtils类。 通过该类中 loadAnimation 方法来加载这些布局文件。
Animation anim = AnimationUtils.loadAnimation(this.getContext(), R.anim.alpha_anim);
animation.setRepeatMode(Animation.REVERSE);
animation.setRepeatCount(Animation.INFINITE);
view.startAnimation(animation);
3.使用动画监听器
动画还可以添加监听事件,监听到动画的开始,结束和重复
mAnimationSet.setAnimationListener(new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
@Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
}
});
4. 为布局和View Group添加动画
(1)AnimateLayoutChanges
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="add"
android:text="Add Button" />
</LinearLayout>
(2)LayoutAnimation
LayoutAnimation可以来为viewGroup添加动画,并按照顺序把一个动画应用到viewGroup中的每一个子View上
xml:
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/more_in"
android:aninationOrder="random"
android:delay="30%"/>
animationOrder,这个是说子view按照什么顺序来执行anim,可以使normal(正常,0-n),reverse(反序,n-0),random(随机)
delay,用于延迟的每个子view的动画开始动画持续时间的浮点数。越大间隔越长。0.3或者30%的字样。
使用动画是直接在viewGroup布局定义中使用android:LayoutAnimation来完成的
android:layoutAnimation="@anim/layout_more_in"
java:
在java中使用 LayoutAnimation要借助LayoutAnimationController
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
sa.setDuration(2000);
// 第二个参数dely : the delay by which each child's animation must be offset
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F);
// 设置显示的顺序 这个必须要在dely不为0的时候才有效
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
ll.setLayoutAnimation(lac);
通常情况下,布局动画会在viewGroup第一次进行布局的时候执行一次,可以通过对viewGroup对象调用scheduleLayoutAnimation强制它再次执行,当viewGroup在下次布局的时候,这个动画会再次执行
viewGroup.scheduleLayoutAnimation();
(3)LayoutTransition
public class AnimateLayoutTransition extends Activity {
private LinearLayout ll;
private LayoutTransition mTransition = new LayoutTransition();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.animate_layout_transition);
ll = (LinearLayout) findViewById(R.id.ll);
setupCustomAnimations();
ll.setLayoutTransition(mTransition);
}
public void add(View view) {
final Button button = new Button(this);
ll.addView(button);
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
ll.removeView(button);
}
});
}
// 生成自定义动画
private void setupCustomAnimations() {
// 动画:CHANGE_APPEARING
// Changing while Adding
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1);
PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1);
PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1);
PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1);
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0f, 1f);
PropertyValuesHolder pvhScaleY = PropertyValuesHolder.ofFloat("scaleY", 1f, 0f, 1f);
final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhScaleX,
pvhScaleY).setDuration(
mTransition.getDuration(LayoutTransition.CHANGE_APPEARING));
mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
changeIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
// View也支持此种动画执行方式了
view.setScaleX(1f);
view.setScaleY(1f);
}
});
// 动画:CHANGE_DISAPPEARING
// Changing while Removing
Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(0.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(this, pvhRotation)
.setDuration(mTransition .getDuration(LayoutTransition.CHANGE_DISAPPEARING));
mTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
changeOut.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotation(0f);
}
});
// 动画:APPEARING
// Adding
ObjectAnimator animIn = ObjectAnimator.ofFloat(null, "rotationY", 90f, 0f).setDuration(
mTransition.getDuration(LayoutTransition.APPEARING));
mTransition.setAnimator(LayoutTransition.APPEARING, animIn);
animIn.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationY(0f);
}
});
// 动画:DISAPPEARING
// Removing
ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotationX", 0f, 90f).setDuration(
mTransition.getDuration(LayoutTransition.DISAPPEARING));
mTransition.setAnimator(LayoutTransition.DISAPPEARING, animOut);
animOut.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator anim) {
View view = (View) ((ObjectAnimator) anim).getTarget();
view.setRotationX(0f);
}
});
}
}
LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画
LayoutTransition.CHANGE_APPEARING当一个View在ViewGroup中出现时,此View对其他View位置造成影响,对其他View设置的动画
LayoutTransition.DISAPPEARING当一个View在ViewGroup中消失时,对此View设置的动画
LayoutTransition.CHANGE_DISAPPEARING当一个View在ViewGroup中消失时,此View对其他View位置造成影响,对其他View设置的动画
LayoutTransition.CHANGE 不是由于View出现或消失造成对其他View位置造成影响,然后对其他View设置的动画。
注意动画到底设置在谁身上,此View还是其他View。