Android Tween和Frame动画

http://blog.csdn.net/dmk877/article/details/51912104

1 补间(Tween)动画

定义补间动画思路:

设置一张图片的开始状态(包括透明度、位置、缩放比、旋转度),并设置该图片的结束状态(包括透明度、位置、缩放比、旋转度),再设置动画的持续时间。

定义动画的XML资源放在/res/anim/路径下,需自行创建该路径。

假设动画显示在ImageView下:

1.1 res/anim目录下添加动画

定义AnimationDrawable资源需指定4个元素:

  • alpha: 设置透明度的改变。

  • scale: 设置图片进行缩放变换。

  • translate: 设置图片进行位移变换。

  • rotate: 设置图片进行旋转。

<set  xmlns:android=”http://schemas.android.com/apk/res/android”
      android:fillAfter=["true" | "false"]
      android:fillBefore=["true" | "false"]
      android:fillEnabled["true" | "false"]
      android:repeatMode=["reverse" | "restart"]
      android:repeatCount="重复播放次数"		
      android:interpolator=”@[package:]anim/interpolator_resource”
      android:shareInterpolator=["true" | "false"]
      android:duration="持续时间"
      android:startOffset="动画多少毫秒后开始">
<alpha
      android:fromAlpha=float”
      android:toAlpha=float/>
<scale
      android:fromXScale=float”
      android:toXScale=float”
      android:fromYScale=float”
      android:toYScale=float”
      android:pivoX=float”
      android:pivoY=float/>
<translate
      android:fromXDelta=float”
      android:toXDelta=float”
      android:fromYDelta=float”
      android:toYDelta=float/>
<rotate
      android:fromDegrees=float”
      android:toDegrees=float”
      android:pivoX=float”
      android:pivoY=float/>
</set>

总体说明:

  • fromXxx、toXxx属性定义图片的开始状态、结束状态。

  • scale和rotate元素需要指定pivoX、pivoY属性来指定scale的“中心点”、rotate的“旋轴点”。

  • interpolator属性指定动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等,Android系统的R.main类中包含了大量常量定义动画速度:

    • linear_interpolator: 匀速变换。

    • accelerate_interpolator: 加速变换。

    • decelerate_interpolator: 减速变换。

想让 <set…/> 元素下所有的变换效果使用相同的动画速度,指定 android:shareInterpolator=”true”

详细说明:

通用属性说明(无论在 <set/> 还是 <alpha/> 其他动画标签都适用)

  • fillAfter:动画执行完成,是否停留在最后一帧(保持动画完成后的状态)

  • fillBefore:动画执行完成,是否还原到开始动画前状态;fillEnable为true时才有意义,否则默认为true

  • fillEnabled:动画执行完成,是否还原到开始动画前状态

  • repeatMode:动画执行完成后的状态(reverse:倒序回放,restart:重新播放一遍);与repeatCount联合使用设置重复播放类型;repeatMode只适用于单个动画,不适合<set/>

  • repeatCount:动画重复次数

  • interpolator:动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等,Android系统的R.main类中包含了大量常量定义动画速度:

    • linear_interpolator: 匀速变换。

    • accelerate_interpolator: 加速变换。

    • decelerate_interpolator: 减速变换。

系统提供的常用interpolator如下:

interpolator对象资源id功能
AccelerateDecelerateInterpolator@android:anim/accelerate_decelerate_interpolator先加速后减速
AccelerateInterpolator@android:anim/accelerate_interpolator加速
AnticipateInterpolator@android:anim/anticipate_interpolator先回退一小步然后加速前进
AnticipateOvershootInterpolator@android:anim/anticipate_overshoot_interpolator先回退一小步然后加速前进,超出终点一小步后再回到终点
BounceInterpolator@android:anim/bounce_interpolator最后阶段弹球效果
CycleInterpolator@android:anim/cycle_interpolator周期运动
DecelerateInterpolator@android:anim/decelerate_interpolator减速
LinearInterpolator@android:anim/linear_interpolator匀速
OvershootInterpolator@android:anim/overshoot_interpolator快速到达终点并超出一小步最后回到终点

自定义Interpolator需要在res/anim新建xml,设置对应的interpolator标签修改相应属性

自定义Interpolator可调整属性:

标签属性
<accelerateDecelerateInterpolator>
<accelerateInterpolator>android:factor 浮点值,加速速率,默认为1
<anticipateInterpolator>android:tension 浮点值,起始点后退的张力、拉力数,默认为2
<anticipateOvershootInterpolator>android:tension 浮点值,起始点后退的张力、拉力数,默认为2;android:extraTension 浮点值,拉力的倍数,默认为1.5(2 * 1.5)
<bounceInterpolator>
<cycleInterpolator>android:cycles 整数值,循环的个数,默认为1
<decelerateInterpolator>android:factor 浮点值,减速的速率,默认为1
<linearInterpolator>
<overshootInterpolator>android:tension 浮点值,超出终点后的张力、拉力,默认为2
  • shareInterpolator:使用相同的动画速度(一般使用在操作多个动画使用)

  • duration:动画时长

  • startOffset:动画在多少毫秒后才开始

某些动画值的设置:

可以是数值、百分数、百分数p;以水平方向为例,数值50,表示当前View的左上角(作为原点)在x轴方向(从左往右)50px作为起始坐标;

百分数50%,表示当前View的左上角在x轴方向以View宽度的50%作为起始坐标;百分数p为50%p,表示当前View的左上角在x轴方向以View的父View宽度的50%作为起始坐标。

  • alpha

    • fromAlpha:动画开始时的透明度,范围为0.0-1.0,0.0完全透明,1.0完全不透明
    • toAlpha:动画结束时的透明度,范围为0.0-1.0,0.0完全透明,1.0完全不透明
  • scale

    • fromXScale:起始的x方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍

    • toXScale:结尾的x方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍

    • fromYScale:起始的y方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍

    • toYScale:结尾的y方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍

    • pivoX:缩放起点x坐标,可以是数值、百分数、百分数p

    • pivoY:缩放起点y坐标,可以是数值、百分数、百分数p

  • translate

    • fromXDelta:起始点x轴坐标,可以是数值、百分数、百分数p

    • toXDelta:结束点x轴坐标,可以是数值、百分数、百分数p

    • fromYDelta:起始点y轴坐标,可以是数值、百分数、百分数p

    • toYDelta:结束点y轴坐标,可以是数值、百分数、百分数p

  • rotate

    • fromDegrees:起始的旋转角度

    • toDegrees:结束的旋转角度(注意是结束的旋转角度,即停留的角度,不是要旋转的角度)

    • pivoX:旋转起点x坐标,可以是数值、百分数、百分数p

    • pivoY:旋转起点的y坐标,可以是数值、百分数、百分数p

1.2 代码添加动画

  • alpha
AlphaAnimation aa = new AlphaAnimation(开始的透明度,结束时的透明度);
  • rotate
RotateAnimation ra = new RotateAnimation(开始的角度,旋转的角度);
  • scale
ScaleAnimation sa = new ScaleAnimation(x轴开始大小,x轴最终大小,y轴开始大小,y轴最终大小);
  • translate
TranslateAnimation ta = new TranslateAnimation(x轴开始坐标,x轴最终坐标,y轴开始坐标,y轴最终坐标);

1.3 加载动画

Animation animation = AnimationUtils.loadAnimation(Context,资源id);

1.4 开启动画

imageView.startAnimation(开启的动画对象);

1.5 组合动画

[1]AnimationSet set = new AnimationSetfalse);
set.addAnimation(动画对象);
…………
[2]加载动画
[3]开启动画

anim目录下:

  • alpha.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置View从完全透明到完全不透明 -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    android:fillAfter="true"
    android:duration="1000"/>
  • rotate.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置从0旋转360度,旋转中心点是View的中心 -->
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="1000"
    android:fillAfter="true"/>
  • scale.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置了水平和垂直坐标从View的两倍开始缩放到自身大小 -->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="2.0"
    android:toXScale="1.0"
    android:fromYScale="2.0"
    android:toYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="1000"
    android:fillAfter="true"/>
  • translate.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置View水平平移自身位置大小的距离 -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="50%"
    android:fromYDelta="0"
    android:toYDelta="0"
    android:duration="1000"
    android:fillAfter="true"/>
  • set.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- View从缩放点0开始扩大到自身大小,伴随着旋转360度和从完全透明到完全不透明,
 以上三种动画执行完成后,开始平移View自身一半大小后,再从完全不透明到完全透明-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <rotate
        android:fromDegrees="0.0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="3000"/>

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

    <scale
        android:fromXScale="0.0"
        android:toXScale="1.0"
        android:fromYScale="0.0"
        android:toYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="3000"/>

    <translate
        android:startOffset="3000"
        android:fromXDelta="0.0"
        android:toXDelta="50%"
        android:duration="1000"/>

    <alpha
        android:startOffset="4000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="1000"/>

</set>
public class TweenAnimActivity extends AppCompatActivity {

    private static final int ANIM_TYPE_ALPHA = 0;
    private static final int ANIM_TYPE_SCALE = 1;
    private static final int ANIM_TYPE_TRANSLATE = 2;
    private static final int ANIM_TYPE_ROTATE = 3;
    private static final int ANIM_TYPE_SET = 4;

    private int mCurrentAnimType;

    private ImageView mIvAnim;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_tween_anim);
        mIvAnim = findViewById(R.id.iv_anim);

        findViewById(R.id.btn_alpha).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCurrentAnimType = ANIM_TYPE_ALPHA;
                doAnim(ANIM_TYPE_ALPHA, 0);
            }
        });
        findViewById(R.id.btn_scale).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCurrentAnimType = ANIM_TYPE_SCALE;
                doAnim(ANIM_TYPE_SCALE, 0);
            }
        });
        findViewById(R.id.btn_translate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCurrentAnimType = ANIM_TYPE_TRANSLATE;
                doAnim(ANIM_TYPE_TRANSLATE, 0);
            }
        });
        findViewById(R.id.btn_rotate).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCurrentAnimType = ANIM_TYPE_ROTATE;
                doAnim(ANIM_TYPE_ROTATE, 0);
            }
        });
        findViewById(R.id.btn_set).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mCurrentAnimType = ANIM_TYPE_SET;
                doAnim(ANIM_TYPE_SET, 0);
            }
        });
        findViewById(R.id.btn_repeat_reverse).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                doAnim(mCurrentAnimType, Animation.REVERSE);
            }
        });
        findViewById(R.id.btn_repeat_restart).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                doAnim(mCurrentAnimType, Animation.RESTART);
            }
        });
    }

    private void doAnim(int animType, int repeatMode) {
        int animRes;
        switch (animType) {
            case ANIM_TYPE_ALPHA:
                animRes = R.anim.alpha;
                break;
            case ANIM_TYPE_SCALE:
                animRes = R.anim.scale;
                break;
            case ANIM_TYPE_TRANSLATE:
                animRes = R.anim.translate;
                break;
            case ANIM_TYPE_ROTATE:
                animRes = R.anim.rotate;
                break;
            case ANIM_TYPE_SET:
                animRes = R.anim.set;
                break;
            default:
                animRes = ANIM_TYPE_ALPHA;
                break;
        }
        Animation animation = AnimationUtils.loadAnimation(this, animRes);
        if (repeatMode != 0) {
            animation.setRepeatCount(1);
            animation.setRepeatMode(repeatMode);
        }
	// 动画监听
	animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                
            }

            @Override
            public void onAnimationEnd(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });
        mIvAnim.startAnimation(animation);
    }
}

2逐帧(Frame)动画

(根元素:<animation-list…/>,在res/drawable目录)

逐帧动画就是把动画过程的每张静态图片收集起来后由Android依次显示出来。

<animation-list  xmlns:android=”http://schemas.android.com/apk/res/android”
	android:oneshot=[true|false]>
  	<item  android:drawable=”@[package:]drawable/drawable_resource_name”
		   android:duration=”integer/>
</animation-list>

说明:

  • android:oneshot:控制该动画是否循环播放,true不会循环,false循环。每个<item…/>子元素增加一帧。
    程序获取AnimationDrawable对象之后,习惯上把AnimationDrawable设置成ImageView背景显示动画。
imageView.setImageResource(动画资源id);
AnimationDrawable drawable = (AnimationDrawable)imageView.getDrawable();
  • drawable目录下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">

    <item android:drawable="@drawable/ic_launcher"
        android:duration="1000"/>

    <item android:drawable="@drawable/ic_launcher_round"
        android:duration="1000"/>

</animation-list>
public class FrameAnimActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frame_anim);

        final ImageView ivAnim = findViewById(R.id.iv_anim);

        findViewById(R.id.btn_start_anim).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ivAnim.setImageResource(R.drawable.frame_anim);
                AnimationDrawable drawable = (AnimationDrawable) ivAnim.getDrawable();
                if (drawable != null) {
                    Log.i("tag", "drawable exist");
                }
            }
        });
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值