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

android中的动画完全总结

2016-06-14 21:59 651 查看
这里会讲到的动画有视图动画(帧动画,补间动画),属性动画,activity和fragment切换时的动画,viewgroup添加和移除子view时的动画,android随后新的系统api的transition,Scene实现过渡效果,内容还是很多的。下面一一来说。
在Android动画中,总共有两种类型的动画View Animation(视图动画)和Property Animator(属性动画);其中
View Animation包括Tween Animation(补间动画)和Frame Animation(逐帧动画);
Property Animator包括ValueAnimator和ObjectAnimation;
1.帧动画:
<span style="font-size:14px;">	/**
* 帧动画就是搞几个图片让他轮播
* 在res/drawable下定义xml文件
* <?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item
android:drawable="@drawable/iv1"
android:duration="150">
</item>
<item
android:drawable="@drawable/iv2"
android:duration="150">
</item>
<item
android:drawable="@drawable/iv3"
android:duration="150">
</item>
</animation-list>
将xml作为imageview的背景图片
代码中调用 imageview.getbackground强转为AnimationDrawable
调用start..
调用stop
*/</span>
2.补间动画:有xml定义或者java文件定义都可以xml中定义:
<span style="font-size:14px;">	 * Android的animation由四种类型组成:alpha、scale、translate、rotate
* 还有个动画集合set可以把以上动画放在一起同时执行
* 可以用xml文件定义res/anim文件夹下
*
* 1.scale标签是缩放动画,可以实现动态调控件尺寸的效果,有下面几个属性:
android:fromXScale    起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
android:toXScale        结尾的X方向上相对自身的缩放比例,浮点值;
android:fromYScale    起始的Y方向上相对自身的缩放比例,浮点值,
android:toYScale        结尾的Y方向上相对自身的缩放比例,浮点值;
android:pivotX            缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
android:pivotY           缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
*
*
* android:fillAfter   如果设置为true,控件动画结束时,将保持动画最后时的状态
* android:fillBefore       如果设置为true,控件动画结束时,还原到开始动画前的状态
*android:repeatCount 重复次数
android:repeatMode	重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
android:interpolator  设定插值器,其实就是指定的动作效果,比如弹跳效果等,不在这小节中讲解,后面会单独列出一单讲解。
*
*
* 2.
* alpha标签——调节透明度
1、自身属性
android:fromAlpha   动画开始的透明度,从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
android:toAlpha       动画结束时的透明度,也是从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明

3.Rotate
android:fromDegrees     开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
android:toDegrees         结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
android:pivotX               缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
android:pivotY               缩放起点Y轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p

4.translate标签所具有的属性为:
android:fromXDelta     起始点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,具体意义已在scale标签中讲述,这里就不再重讲
android:fromYDelta    起始点Y轴从标,可以是数值、百分数、百分数p 三种样式;
android:toXDelta         结束点X轴坐标
android:toYDelta        结束点Y轴坐标
*
*/</span>
除了上面4个外,还有一个AnimationSet,是可以将上面动画组合在一起的。xml中定义后,使用下面的代码应用动画,
<span style="font-size:14px;">	public static void start(View view){
//		AnimationSet set = new AnimationSet(true);
//		set.addAnimation(AnimationUtils.loadAnimation(this, R.anim.scale_anim));
//		set.addAnimation(AnimationUtils.loadAnimation(this, R.anim.alpha_anim));
//		set.addAnimation(AnimationUtils.loadAnimation(this, R.anim.rotate_anim));
//
//		set.setAnimationListener(new AnimationListener() {
//			@Override
//			public void onAnimationStart(Animation animation) {
//			}
//
//			@Override
//			public void onAnimationRepeat(Animation animation) {
//			}
//
//			@Override
//			public void onAnimationEnd(Animation animation) {
//				view.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.translate_anim));
//			}
//		});
//		view.startAnimation(set);

view.startAnimation(AnimationUtils.loadAnimation(view.getContext(), R.anim.set_anim));
}</span>
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<alpha
android:duration="2500"
android:fromAlpha="0"
android:toAlpha="1" />
</set></span>
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<set>

<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
</rotate>

</set></span>
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0"
android:toXScale="1"
android:fromYScale="0"
android:toYScale="1"
android:pivotX="67%p"
android:pivotY="67%p"
android:duration="2500" />

</set></span>
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fillAfter="true"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="67%p"
android:toYDelta="67%p" >
</translate>

</set></span>
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
</rotate>

<alpha
android:duration="2500"
android:fromAlpha="0"
android:toAlpha="1" />

<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="67%p"
android:pivotY="67%p"
android:toXScale="1"
android:toYScale="1" />

<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fromXDelta="0"
android:fromYDelta="0"
android:startOffset="2500"
android:toXDelta="67%p"
android:toYDelta="67%p" >
</translate>

</set></span>
<span style="font-size:14px;"><?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000" >

<translate
android:fromXDelta="-50%p"
android:toXDelta="0" />

<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />

</set></span>
java代码创建补间动画,只是根据xml中定义的,翻译成java代码就可以了。如xml中定义了,
<span style="font-size:14px;">	/**
* 代码生成animation。xml文件对应的Java类
* 	TranslateAnimation
RotateAnimation
ScaleAnimation
AlphaAnimation
我们可以根据xml中的属性翻译过来就行了
*/

//例如这个:
/**
* <?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fillAfter="true"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" >
</rotate>

<alpha
android:duration="2500"
android:fromAlpha="0"
android:toAlpha="1" />

<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="67%p"
android:pivotY="67%p"
android:toXScale="1"
android:toYScale="1" />

<translate
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2500"
android:fromXDelta="0"
android:fromYDelta="0"
android:startOffset="2500"
android:toXDelta="67%p"
android:toYDelta="67%p" >
</translate>

</set>
*/</span>
那么如果我们用java代码来生成的话就是这样的:
<span style="font-size:14px;">	public static void start(View view){
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotateAnimation.setFillAfter(true);
rotateAnimation.setDuration(2500);

AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(2500);

ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, Animation.RELATIVE_TO_PARENT,0.67f, Animation.RELATIVE_TO_PARENT, 0.67f);
scaleAnimation.setDuration(2500);

TranslateAnimation translateAnimation = new TranslateAnimation( Animation.RELATIVE_TO_PARENT, 0,  Animation.RELATIVE_TO_PARENT, 0.67f,  Animation.RELATIVE_TO_PARENT, 0,  Animation.RELATIVE_TO_PARENT, 0.67f);
translateAnimation.setStartOffset(2500);
translateAnimation.setDuration(2500);

AnimationSet set = new AnimationSet(true);
set.addAnimation(rotateAnimation);
set.addAnimation(alphaAnimation);
set.addAnimation(scaleAnimation);
set.addAnimation(translateAnimation);
view.startAnimation(set);
}</span>
上面的代码还是很简单的,想想如果位置从A平移到B,是应该以什么样的速率来移动呢,默认的是匀速了,所有你也可以指定或者自定义动画过程中要用到的插值器,Interpolator插值器,用来定义动画执行过程中的具体行为,变化速率。插值器也可以用在属性动画上。
/**
*Interpolator插值器,用来定义动画执行过程中的具体行为,变化速率
*
*已经定义好了的插值器有这些
*AccelerateDecelerateInterpolator   在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator                     在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator                      开始的时候向后然后向前甩
AnticipateOvershootInterpolator     开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator                          动画结束的时候弹起
CycleInterpolator                             动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator                    在动画开始的地方快然后慢
LinearInterpolator                            以常量速率改变
OvershootInterpolator                      向前甩一定值后再回到原来位置
*/
应用插值器,
public static void useSystemInterpolator(View view,Interpolator i){
AnimationSet set = new AnimationSet(true);
set.addAnimation(AnimationUtils.loadAnimation(view.getContext(), R.anim.scale_anim));
set.setInterpolator(i);
view.startAnimation(set);
}
3.属性动画,也可以用xml或者java定义。涉及到2个类
ValueAnimator,这个本身不能对view造成动画效果,它是根据指定属性的起始值,可选指定插值器,添加监听动画回调变化过程中的返回值,根据返回值来动态改变view的属性值。
ObjectAnimator,对象动画,直接作用于view
/**
* 补间动画虽能对控件做动画,但并没有改变控件内部的属性值。 比如平移后,虽然外观上位置看像移动了,其实是没有移动
*
* 属性动画,ValueAnimator; 它本身不会对任何view做操作,需要我们监听它的值变化,
* 在变化中自己改变view的值,从而实现动画.至于这个区间的值变化是怎样的,我们可以自己去
* 设置它的animator.setInterpolator(new BounceInterpolator());
*
* 而和它的子类ObjectAnimator关联了我们要动画的对象,这样子我们就不需要
* 每次监听变化了
*/
xml定义,
/**
* xml文件中定义属性动画
* 标签对应;
* <value_animator />:对应ValueAnimator
<objectAnimator />:对应ObjectAnimator
<set />:对应AnimatorSet
*
* <value_animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]
android:interpolator=["@android:interpolator/XXX"]/>
*/
public static void loadXmlAnimator(final View view){
//        ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(view.getContext(), R.animator.value_animator);
//        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//            @Override
//            public void onAnimationUpdate(ValueAnimator animation) {
//                int offset = (int)animation.getAnimatedValue();
//                view.layout( offset,offset,view.getWidth()+offset,view.getHeight() + offset);
//            }
//        });
//        valueAnimator.start();

//        ObjectAnimator objectAnimator = (ObjectAnimator) AnimatorInflater.loadAnimator(view.getContext(), R.animator.object_animator);
//        objectAnimator.setTarget(view);
//        objectAnimator.start();

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(view.getContext(), R.animator.set_animator);
set.setTarget(view);
set.start();
}
<?xml version="1.0" encoding="utf-8"?><objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:propertyName="TranslationY"android:duration="2000"android:valueFrom="0.0"android:valueTo="400.0"android:interpolator="@android:anim/accelerate_interpolator"android:valueType="floatType"android:repeatCount="1"android:repeatMode="reverse"android:startOffset="2000"/>
<?xml version="1.0" encoding="utf-8"?><objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"android:propertyName="rotation"android:repeatCount="1"android:valueFrom="0"android:valueTo="360"android:valueType="floatType" ></objectAnimator>
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"android:ordering="together"><objectAnimatorandroid:propertyName="x"android:duration="2500"android:valueFrom="0"android:valueTo="400"android:valueType="floatType"/><objectAnimatorandroid:propertyName="y"android:duration="2500"android:valueFrom="0"android:valueTo="300"android:valueType="floatType"/></set>
<?xml version="1.0" encoding="utf-8"?><animator xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:interpolator="@android:anim/bounce_interpolator"android:startOffset="2000"android:valueFrom="0"android:valueTo="300"android:valueType="intType" />
java中定义,
package com.example.customeviewserial.property_animation;import android.animation.Animator;import android.animation.Animator.AnimatorListener;import android.animation.AnimatorInflater;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.animation.AccelerateInterpolator;import android.view.animation.BounceInterpolator;import android.widget.ImageView;import android.widget.RelativeLayout;import com.example.customeviewserial.R;/*** GroupFlexBoll提供一个例子说明用java代码创建属性动画*关键代码startTranslate()方法*  */public class GroupFlexBoll extends RelativeLayout {private static final int[] BTN_RES = { R.drawable.home,R.drawable.iv1, R.drawable.iv2,R.drawable.iv3 };private static final int SWAP_ANGLE = 90;private static final int BOLLNUM = 3;private static final float SPACE_ANGLE = SWAP_ANGLE / (BOLLNUM - 1);RelativeLayout.LayoutParams params;private int radius;private ImageView homeImageView;private ImageView iv1;private ImageView iv2;private ImageView iv3;public GroupFlexBoll(Context context, AttributeSet attrs) {super(context, attrs);addView(context);}private void addView(Context context) {homeImageView = new ImageView(context);homeImageView.setTag("home");params = new RelativeLayout.LayoutParams(40, 40);params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);homeImageView.setImageResource(BTN_RES[0]);addView(homeImageView, params);iv1 = new ImageView(context);iv1.setImageResource(BTN_RES[1]);iv1.setTag("iv1");addView(iv1, params);iv2 = new ImageView(context);iv2.setImageResource(BTN_RES[2]);iv2.setTag("iv2");addView(iv2, params);iv3 = new ImageView(context);iv3.setImageResource(BTN_RES[3]);iv3.setTag("iv3");addView(iv3, params);setSubBtnVisible(false);}public void setOperationListener(OnClickListener l) {homeImageView.setOnClickListener(l);iv1.setOnClickListener(l);iv2.setOnClickListener(l);iv3.setOnClickListener(l);}private void setSubBtnVisible(boolean isVisible) {if (isVisible) {iv1.setVisibility(View.VISIBLE);iv2.setVisibility(View.VISIBLE);iv3.setVisibility(View.VISIBLE);} else {iv1.setVisibility(View.GONE);iv2.setVisibility(View.GONE);iv3.setVisibility(View.GONE);}}private void setSubBtnEnable(boolean isEnabled){if(isEnabled){iv1.setEnabled(true);iv2.setEnabled(true);iv3.setEnabled(true);}else{iv1.setEnabled(false);iv2.setEnabled(false);iv3.setEnabled(false);}}private boolean isOpend = false;private int boll_radius;public void toggle() {isOpend = !isOpend;doAnimation();}private void doAnimation() {setSubBtnVisible(true);startTranslate();}private void startTranslate() {int willTranslateLen = boll_radius * 2 * 3;ObjectAnimator animator1Y, animator2Y, animator3Y, animator1X, animator2X, animator3X;if (isOpend) {animator1Y = ObjectAnimator.ofFloat(iv1, "translationY", 0,-willTranslateLen);animator2Y = ObjectAnimator.ofFloat(iv2, "translationY", 0,(float) (-willTranslateLen * Math.cos(Math.toRadians(45))));animator3Y = ObjectAnimator.ofFloat(iv3, "translationY", 0, 0);animator1X = ObjectAnimator.ofFloat(iv1, "translationX", 0, 0);animator2X = ObjectAnimator.ofFloat(iv2, "translationX", 0,(float) (-willTranslateLen * Math.sin(Math.toRadians(45))));animator3X = ObjectAnimator.ofFloat(iv3, "translationX", 0,(float) (-willTranslateLen * Math.sin(Math.toRadians(90))));} else {animator1Y = ObjectAnimator.ofFloat(iv1, "translationY",-willTranslateLen, 0);animator2Y = ObjectAnimator.ofFloat(iv2, "translationY",(float) (-willTranslateLen * Math.cos(Math.toRadians(45))),0);animator3Y = ObjectAnimator.ofFloat(iv3, "translationY", 0, 0);animator1X = ObjectAnimator.ofFloat(iv1, "translationX", 0, 0);animator2X = ObjectAnimator.ofFloat(iv2, "translationX",(float) (-willTranslateLen * Math.sin(Math.toRadians(45))),0);animator3X = ObjectAnimator.ofFloat(iv3, "translationX",(float) (-willTranslateLen * Math.sin(Math.toRadians(90))),0);}Animator rotateAnimator1 = AnimatorInflater.loadAnimator(getContext(), R.animator.rotate);Animator rotateAnimator2 = AnimatorInflater.loadAnimator(getContext(), R.animator.rotate);Animator rotateAnimator3 = AnimatorInflater.loadAnimator(getContext(), R.animator.rotate);rotateAnimator1.setTarget(iv1);rotateAnimator2.setTarget(iv2);rotateAnimator3.setTarget(iv3);rotateAnimator1.setDuration(100);rotateAnimator2.setDuration(100);rotateAnimator3.setDuration(100);AnimatorSet set = new AnimatorSet();set.addListener(new AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {homeImageView.setEnabled(false);setSubBtnEnable(false);}@Overridepublic void onAnimationRepeat(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {if (isOpend == false) {setSubBtnVisible(false);}else{setSubBtnEnable(true);}homeImageView.setEnabled(true);}@Overridepublic void onAnimationCancel(Animator animation) {}});set.playTogether(animator1Y, animator2Y, animator3Y, animator1X,animator2X, animator3X,rotateAnimator1,rotateAnimator2,rotateAnimator3);set.setDuration(1500);if(isOpend){set.setInterpolator(new BounceInterpolator());}else{set.setInterpolator(new AccelerateInterpolator());}set.start();}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (changed) {int measuredWidth = getMeasuredWidth();int measuredHeight = getMeasuredHeight();radius = Math.min(measuredWidth, measuredHeight);measureBtnSize();}}private void measureBtnSize() {params.width = radius / 4;params.height = radius / 4;boll_radius = radius / 8;homeImageView.setLayoutParams(params);iv1.setLayoutParams(params);iv2.setLayoutParams(params);iv3.setLayoutParams(params);}}
控制动画顺序,
package com.example.customeviewserial.set_order_animator;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.view.View;/*** Created by Administrator on 2016/5/24 0024.*/public class GuideUser {/*** AnimatorSet实现的属性动画集合,* 控制各个动画的执行顺序* playSequentially,playTogether*/public static void startAnimatorSet(View... view){ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(view[0], "BackgroundColor",  0xffff00ff, 0xffffff00, 0xffff00ff);ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(view[1], "translationY", 0, 300, 0);ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(view[2], "translationY", 0, 400, 0);AnimatorSet animatorSet = new AnimatorSet();//      animatorSet.playSequentially(tv1BgAnimator,tv1TranslateY,tv2TranslateY);animatorSet.playTogether(tv1BgAnimator,tv1TranslateY,tv2TranslateY);//自由设置动画顺序——AnimatorSet.BuilderAnimatorSet.Builder builder = animatorSet.play(tv1BgAnimator);/*** //和前面动画一起执行public Builder with(Animator anim)//执行先执行这个动画再执行前面动画public Builder before(Animator anim)//执行前面的动画后才执行该动画public Builder after(Animator anim)//延迟n毫秒之后执行动画public Builder after(long delay)*///AnimatorSet没有统一设置的情况下,各自按各自的来。这里统一设置了时间,会覆盖各自的时间animatorSet.setDuration(1000);animatorSet.start();}}
4.viewgroup初始化,viewgroup中添加和移除子view时添加动画;
涉及到LayoutTransition和之前提到的属性动画;
	/*** 普通viewGroup添加进入统一动画的LayoutAnimation* 和针对grideView添加进入动画的gridLayoutAnimation; 这2个类只能保证在创建的时候有动画。** android:animateLayoutChanges==true可以为任何viewgroup控件加上默认动画* 和LayoutTransition则可以来自定义动画** 1.可以在xml文件中指定* 在anim文件夹中定义<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"android:animation="@anim/slide_in_left"android:animationOrder="normal"android:delay="1" />delay值是animation时间值的倍数animation引用的只能是animation动画,不能是animator定义好后,在layout中引用  android:layoutAnimation="@anim/layout_animation"动画只在第一次创建容器的时候有动画android:animationOrder指viewGroup中的控件动画开始顺序,取值有normal(正序)、reverse(倒序)、random(随机)2.可以在Java文件中指定//代码设置通过加载XML动画设置文件来创建一个Animation对象;Animation animation= AnimationUtils.loadAnimation(this,R.anim.slide_in_left);   //得到一个LayoutAnimationController对象;LayoutAnimationController controller = new LayoutAnimationController(animation);   //设置控件显示的顺序;controller.setOrder(LayoutAnimationController.ORDER_REVERSE);   //设置控件显示间隔时间;controller.setDelay(0.3f);   //为ListView设置LayoutAnimationController属性;mListView.setLayoutAnimation(controller);mListView.startLayoutAnimation();对应的GridView:Animation animation = AnimationUtils.loadAnimation(MyActivity.this,R.anim.slide_in_left);GridLayoutAnimationController controller = new GridLayoutAnimationController(animation);controller.setColumnDelay(0.75f);controller.setRowDelay(0.5f);controller.setDirection(GridLayoutAnimationController.DIRECTION_BOTTOM_TO_TOP|GridLayoutAnimationController.DIRECTION_LEFT_TO_RIGHT);controller.setDirectionPriority(GridLayoutAnimationController.PRIORITY_NONE);grid.setLayoutAnimation(controller);grid.startLayoutAnimation();3.LayoutTransition则可以来为viewgroup自定义添加属性动画LayoutTransaction transitioner = new LayoutTransition();ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f);transitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);linearLayout.setLayoutTransition(mTransitioner);第一个参数int transitionType:表示当前应用动画的对象范围,取值有:APPEARING —— 元素在容器中出现时所定义的动画。DISAPPEARING —— 元素在容器中消失时所定义的动画。CHANGE_APPEARING —— 由于容器中要显现一个新的元素,其它需要变化的元素所应用的动画CHANGE_DISAPPEARING —— 当容器中某个元素消失,其它需要变化的元素所应用的动画*/
/*** 测试LayoutTransition效果* 这里有几点注意事项:1、LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须使用PropertyValuesHolder所构造的动画才会有效果,不然无效!也就是说使用ObjectAnimator构造的动画,在这里是不会有效果的!2、在构造PropertyValuesHolder动画时,”left”、”top”属性的变动是必写的。如果不需要变动,则直接写为:PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,0);PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,0);3、在构造PropertyValuesHolder时,所使用的ofInt,ofFloat中的参数值,第一个值和最后一个值必须相同,不然此属性所对应的的动画将被放弃,在此属性值上将不会有效果;PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,100,0);比如,这里ofInt(“left”,0,100,0)第一个值和最后一个值都是0,所以这里会有效果的,如果我们改为ofInt(“left”,0,100);那么由于首尾值不一致,则将被视为无效参数,将不会有效果!4、在构造PropertyValuesHolder时,所使用的ofInt,ofFloat中,如果所有参数值都相同,也将不会有动画效果。比如*/
下面是一个具体例子,
	/***为viewgroup应用LayoutTransition动画*/private void useLayoutTransition() {LayoutTransition layoutTransition = new LayoutTransition();boolean checked = radio_appear.isChecked();boolean checked2 = radio_disappear.isChecked();boolean checked3 = radio_change_appear.isChecked();boolean checked4 = radio_change_disappear.isChecked();if (checked || checked2 || checked3 || checked4) {} else {return;}if (checked) { // 自身动画添加ObjectAnimator appearAnimator = ObjectAnimator.ofFloat(null,"alpha", 0, 1);layoutTransition.setAnimator(LayoutTransition.APPEARING,appearAnimator);}if (checked2) { // 自身移除动画ObjectAnimator disappearAnimator = ObjectAnimator.ofFloat(null,"alpha", 1, 0);layoutTransition.setAnimator(LayoutTransition.DISAPPEARING,disappearAnimator);}if (checked3) { // 自身添加时对其他控件应用的动画PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0, 100, 0);PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0,0);Animator changeAppearAnimator = ObjectAnimator.ofPropertyValuesHolder(layout, pvhLeft, pvhTop);layoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING,changeAppearAnimator);}if (checked4) { // 自身移除时对其他控件应用的动画PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0, 0);PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0,0);PropertyValuesHolder pvhRotateX = PropertyValuesHolder.ofFloat("rotationX", 0,180, 0);Animator changeDisAppearAnimator = ObjectAnimator.ofPropertyValuesHolder(layout, pvhLeft, pvhTop,pvhRotateX);layoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,changeDisAppearAnimator);}layoutTransition.setDuration(1000);//		layoutTransition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, 500);layoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 100);layoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 100);//其他条目动画时的间隔layout.setLayoutTransition(layoutTransition);}
5.在activity和fragment进入和退出时运用动画。这些动画都是对activity或者fragment整体的所有布局元素统一进行相同的动画。
activity的进入和退出的动画,我们可以使用代码中应用:
在startActivity或者finish之后调用overridePendingTransition(int enterAnim,int exitAnim);
这里的动画id是xml中定义的视图动画,enterAnim是进入的那个activity的动画,exitAnim是退出的那个activity的动画。
还有一种方法是使用主题的方式为application或者activity指定主题,例如,
定义主题:
	<style name="FeelyouWindowAnimTheme" parent="@android:style/Animation.Activity"><item name="android:activityOpenEnterAnimation">@anim/in_from_left</item><item name="android:activityOpenExitAnimation">@anim/out_from_right</item><item name="android:activityCloseEnterAnimation">@anim/in_from_right</item><item name="android:activityCloseExitAnimation">@anim/out_from_left</item></style><style name="AnimActivityTheme"><item name="android:windowAnimationStyle">@style/FeelyouWindowAnimTheme</item></style>
res/anim/下定义一些视图动画:
in_from_left.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:duration="250"android:fromXDelta="100%p"android:toXDelta="0" /></set>
in_from_right.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:duration="250"android:fromXDelta="-100%p"android:toXDelta="0" /></set>
out_from_left.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:duration="250"android:fromXDelta="0"android:toXDelta="100%p" /></set>
out_from_right.xml
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:duration="250"android:fromXDelta="0"android:toXDelta="-100%p" /></set>
应用主题:
  <applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AnimActivityTheme"><activity android:name=".MainActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".Main2Activity"></activity></application>
fragment的进入和退出动画如下:请使用v4包下的Fragment保证兼容,在fragmentTransition提交之前应用动画就行;
  if (null == mFragmentManager) {mFragmentManager = getSupportFragmentManager();}fragment = new BlankFragment();FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();fragmentTransaction.setCustomAnimations(R.anim.in_from_left,R.anim.out_from_right,R.anim.in_from_right,R.anim.out_from_left);fragmentTransaction.add(R.id.container, fragment);fragmentTransaction.addToBackStack(null);fragmentTransaction.commit();
6.android5.0为我们提供了一种针对activity或者fragment切换过渡时的新动画,不像上面的过渡动画是针对整个的布局元素执行的是同一个动画,android5.0的过渡动画更加丰富,可以针对其中的共享某些元素执行动画。可以根据原理自己写效果了。提供了三种Transition类型:进入:一个进入的过渡(动画)决定activity中的所有的视图怎么进入屏幕。退出:一个退出的过渡(动画)决定一个activity中的所有视图怎么退出屏幕。共享元素:一个共享元素过渡(动画)决定两个activities之间的过渡,怎么共享(它们)的视图。
</pre><p><pre name="code" class="java"> Transition过渡可以在xml文件中定义或者Java代码创建对应的类,例如在res/transition文件夹下定义它的节点可以是Transition的子类,ChangeBoundsChangeClipBoundsChangeImageTransformChangeTransformTransitionSetExplodeFadeSlideTransitionInflater提供将xml中定义的transition转为transition对象TransitionManager管理Scene和TransitionTransitionDrawable实现drawable有过渡效果
changeBounds -  改变目标视图的布局边界changeClipBounds - 裁剪目标视图边界changeTransform - 改变目标视图的缩放比例和旋转角度changeImageTransform - 改变目标图片的大小和缩放比例过渡动画的执行时机;并且传入一个你想要执行的动画Window.setEnterTransition():设置进入动画Window.setExitTransition():设置退出效果Window.setSharedElementEnterTransition():设置共享元素的进入动画Window.setSharedElementExitTransition():设置共享元素的退出动画具体使用:/ /允许使用transitionsgetWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);//设置一个transitiongetWindow().setExitTransition(new Explode());//new Slide()  new Fade() ;//跳转startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());为共享元素执行过渡动画时,有点不同:使用android:transitionName属性给两个布局中的共享元素指定一个相同的名字(名字一定不要写错)然后执行:startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this,view,"shareName").toBundle());如果有多个共享元素使用:ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,Pair.create(view1, "agreedName1"),Pair.create(view2, "agreedName2"));退出要使用:在代码中触发通过finishAfterTransition()方法触发返回动画,而不是调用finish()方法.7.Scene的使用:api19开始才有的特性,Scene场景,常见使用方法,   public Scene(ViewGroup sceneRoot, View layout)  public static Scene getSceneForLayout(ViewGroup sceneRoot, int layoutId, Context context)  Transition过渡,内部包含场景转换时的动画。可能对SurfaceView,TextureView不起作用。 工作原理是,捕捉两个Scene的状态,根据这2个状态的区别创建属性动画Animator.实际上是对属性动画的一个应用,使用更简单的api实现 了复杂的功能。 这些优点将使得我们只用少量代码就可以创建复杂的Activity和Fragment切换动画使用步骤:应用scene transition 场景转换 1.创建transition 从xml中Transition mFadeTransition =        TransitionInflater.from(this).        inflateTransition(R.transition.fade_transition);从java中创建,TransitionmFadeTransition = new Fade();2.使用TransitionManager.go(mEndingScene, mFadeTransition);res/transition/fade_transition.xml<?xml version="1.0" encoding="utf-8"?><fade xmlns:android="http://schemas.android.com/apk/res/android" />例子:
package com.example.androidtest;import android.annotation.TargetApi;import android.app.Activity;import android.graphics.drawable.TransitionDrawable;import android.os.Build;import android.os.Bundle;import android.transition.AutoTransition;import android.transition.Scene;import android.transition.TransitionManager;import android.view.View;import android.view.animation.AccelerateDecelerateInterpolator;import android.widget.ImageView;import android.widget.RelativeLayout;@TargetApi(Build.VERSION_CODES.KITKAT)public class MainActivity extends Activity {private AutoTransition transition;private Scene scene1;private Scene scene2;private boolean start;private ImageView iv;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.start_layout);iv = (ImageView)findViewById(R.id.iv);// get the root layout IDRelativeLayout rootLayout = (RelativeLayout) findViewById(R.id.base);//场景的定义,首先根布局要一样且定义id;每个场景中具有相同id的视为同一个view实现过渡效果,不同的id则只是简单的渐隐渐显scene1 = Scene.getSceneForLayout(rootLayout, R.layout.start_layout,this);scene2 = Scene.getSceneForLayout(rootLayout, R.layout.end_layout, this);// create transition, set properties//代码创建过渡,也可以使用xml中定义过渡,再使用TransitionInflater.from(this).inflateTransition(resource)解析transition = new AutoTransition();transition.setDuration(2000);transition.setInterpolator(new AccelerateDecelerateInterpolator());// initialize flagstart = true;}/*** 下面几个效果需要api21* ChangeBoundsChangeClipBoundsChangeImageTransformChangeTransformTransitionSetExplodeFadeSlide* @param v*/public void changeScene(View v) {// check flagif (start) {TransitionManager.go(scene2, transition);start = false;} else {TransitionManager.go(scene1, transition);start = true;}//TransitionDrawable是针对图片之间的过渡TransitionDrawable drawable = (TransitionDrawable) iv.getBackground();drawable.startTransition(2000);}}
start_layout.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/base"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ff000000"tools:context=".TransitionsActivity" ><ImageViewandroid:id="@+id/iv"android:layout_width="100dp"android:layout_height="100dp"android:layout_centerInParent="true"android:background="@drawable/transitiondrawable" /><ImageButtonandroid:id="@+id/btn1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:background="#00000000"android:contentDescription="shape"android:onClick="changeScene"android:src="@drawable/shape1" /><ImageButtonandroid:id="@+id/btn2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:background="#00000000"android:contentDescription="shape"android:onClick="changeScene"android:src="@drawable/shape2" /><ImageButtonandroid:id="@+id/btn3"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"android:background="#00000000"android:contentDescription="shape"android:onClick="changeScene"android:src="@drawable/shape3" /><ImageButtonandroid:id="@+id/btn4"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:background="#00000000"android:contentDescription="shape"android:onClick="changeScene"android:src="@drawable/shape4" /></RelativeLayout>
end_layout.xml
<?xml version="1.0" encoding="utf-8"?><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:background="#ff000000"android:id="@+id/base"tools:context=".TransitionsActivity"><ImageButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/btn1"android:src="@drawable/shape1"android:background="#00000000"android:contentDescription="shape"android:layout_alignParentRight="true"android:layout_alignParentBottom="true"android:onClick="changeScene"/><ImageButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/btn2"android:src="@drawable/shape2"android:background="#00000000"android:contentDescription="shape"android:layout_alignParentLeft="true"android:layout_alignParentBottom="true"android:onClick="changeScene"/><ImageButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/btn3"android:src="@drawable/shape3"android:background="#00000000"android:contentDescription="shape"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:onClick="changeScene"/><ImageButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/btn4"android:src="@drawable/shape4"android:background="#00000000"android:contentDescription="shape"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:onClick="changeScene"/></RelativeLayout>
res/drawable/transitiondrawable.xml
<?xml version="1.0" encoding="utf-8"?><transition xmlns:android="http://schemas.android.com/apk/res/android" ><item android:drawable="@drawable/shape1"></item><item android:drawable="@drawable/shape2"></item></transition>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: