Android动画分为View动画,帧动画和视图动画


视图动画

View动画只支持平移,缩放,旋转,透明度的变换效果,通过状态的渐变来产生动画效果.
View动画有两种定义方法,一种是xml定义,另一种是通过代码生成

xml定义

在res/anim下创建动画定义的xml文件,格式如下

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

位置移动(TranslateAnimation)

<translate
android :fromXDelta="10"     //初始位置X轴
android :fromYDelta="10"     //初始位置Y轴
android :toXDelta="100"     //结束位置X轴
android :toYDelta="100"     //结束位置Y轴
android :duration="200"     //动画时长
android :fillAfter="true"     //动画结束时是否返回起始位置
/>

旋转(RotateAnimation)

<rotate
android :fromDegrees="0"     //初始角度
android :toDegrees="+270"     //结束角度 +表示顺时针 -逆时针
android :pivotX="50%"          //旋转中心点X轴
android :pivotY="50%"          //旋转中心点Y轴
android :duration="200"
android :fillAfter="true"
/>

尺寸变化(ScaleAnimation)

<scale
android :fromXScale="1.0"     //初始比例X轴
android :fromYScale="1.0"     //初始比例Y轴
android :toXScale="2.0"          //结束比例X轴
android :toYScale="2.0"          //结束比例Y轴
android :pivotX="50%"          //缩放中心点X轴
android :pivotY="50%"          //缩放中心点Y轴
android :duration="200"
android :fillAfter="true"
/>

透明度变化(AlphaAnimation)

<alpha
android :fromAlpha="0.1"     //初始透明度
android :toAlpha="0.1"          //结束透明度
android :duration="200"        
android :fillAfter="true"
/>

使用

//创建动画
Animation animation = AnimationUtils.loadAnimation(AnimationActivity.this, R.anim.anim_tester_1);
//view上使用动画
view_item.startAnimation(animation) ;

另一种是在代码中定义动画

1.位置移动(TranslateAnimation)

ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f);
scaleAnimation.setDuration(200);
v.startAnimation(scaleAnimation);

2.旋转(RotateAnimation)

TranslateAnimation translateAnimation = new TranslateAnimation(10, 100, 10, 100);
translateAnimation.setDuration(200);
v.startAnimation(translateAnimation);

3.尺寸变化(ScaleAnimation)

RotateAnimation rotateAnimation = new RotateAnimation(0, 90);
rotateAnimation.setDuration(200);
v.startAnimation(rotateAnimation);

4.透明度变化(AlphaAnimation)

AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0.5f);
alphaAnimation.setDuration(200);
v.startAnimation(alphaAnimation);

View动画可以在ViewGroup中控制子元素的出场效果,或者Activity之间的切换效果

Activity跳转的动画效果

在startActivity后面调用overridePendingTransition,两个参数代表新Activty进入和旧Activty退出的动画,两个动画注意时间必须相等

Intent intent = new Intent(MainActivity.this, DestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.wrap_enter_in, R.anim.wrap_enter_out);

Activty退出的时候也可以使用动画,在onBackPressed方法中使用

public void onBackPressed() {
    super.onBackPressed();
    overridePendingTransition(R.anim.wrap_exit_in,R.anim.wrap_exit_out);
}

示例

新Activity向左滑动进入,向右滑动退出

进入动画

wrap_enter_in.xml
<translate
    android:duration="250"
    android:fromXDelta="100%p"
    android:toXDelta="0%p"
    android:fillAfter="true"/>

wrap_enter_out.xml
<translate
    android:duration="250"
    android:fromXDelta="0%p"
    android:toXDelta="-100%p"
    android:fillAfter="true"/>

退出动画

wrap_exit_in.xml
<translate
    android:duration="250"
    android:fromXDelta="-100%p"
    android:toXDelta="0%p"
    android:fillAfter="true"/>

wrap_exit_out.xml
<translate
    android:duration="250"
    android:fromXDelta="0%p"
    android:toXDelta="100%p"
    android:fillAfter="true"/>

属性动画

Android 3.0之后出现了属性动画.
视图动画(补间动画)只能作用于View对象,而且只有移动,旋转,尺寸变化,透明度四种效果.只改变View的显示外观不能修改属性 属性动画是通过对目标对象不断的修改属性来实现动画效果

有关类

ValueAnimator

属性动画的运行机制是通过不断地对值进行操作来实现的,通过不断控制值的变化,再不断手动赋给对象的属性,从而实现动画效果。而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。相当于一个计数器

ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100);
valueAnimator.setDuration(1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Log.v("AnimateValue", String.valueOf(animation.getAnimatedValue()));
    }
});
valueAnimator.start();

ValueAnimator

属性动画机制中 最核心的一个类
实现动画的原理:通过不断控制 值 的变化,再不断 手动 赋给对象的属性,从而实现动画效果。

ValueAnimatior类的方法

  • ofInt()
  • ofFloat()
  • ofObject()

ifInt(0, 100, 0) 参数为任意多个整形数,赋给对象的值在这些范围内变化,从开始值过渡到结束值,ofFloat同理

ofObject() 将初始值以对象的形式过渡到结束值

使用object类型作为动画数值范围需要自定义TypeEvaluator(估值器)

TypeEvaluator<Point> typeEvaluator = new TypeEvaluator<Point>() {
    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        long newX = (long) (fraction * (endValue.x - startValue.x));
        long newY = (long) (fraction * (endValue.y - startValue.y));

        return new Point(newX, newY);
    }
};

Point p1 = new Point(0, 0);
Point p2 = new Point(30, 50);
ValueAnimator valueAnimator1 = ValueAnimator.ofObject(typeEvaluator, p1, p2);
valueAnimator1.setDuration(1000);
valueAnimator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        Point point = (Point) animation.getAnimatedValue();
        Log.v("ValueAnimator", point.toString());

    }
});
valueAnimator1.start();

ObjectAnimator
对任意的对象进行动画操作的类

ObjectAnimator animator = ObjectAnimator.ofFloat(destTextView, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();

参数: 执行动画的view, 改变的属性, 之后的数字是属性值的变化列表,属性值会按次序改变

ObjectAnimator与 ValueAnimator类的区别:

  • ValueAnimator 类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接 对对象属性进行操作;
  • ObjectAnimator 类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接 对对象属性进行操作;

组合动画AnimationSet类

  • AnimatorSet.play(Animator anim) :播放当前动画
  • AnimatorSet.after(long delay) :将现有动画延迟x毫秒后执行
  • AnimatorSet.with(Animator anim) :将现有动画和传入的动画同时执行
  • AnimatorSet.after(Animator anim) :将现有动画插入到传入的动画之后执行
  • AnimatorSet.before(Animator anim) : 将现有动画插入到传入的动画之前执行

组合动画使用

AnimatorSet animSet = new AnimatorSet(); //创建Animationset
animSet.play(anim1).with(anim2).before(anim3); //组合播放动画的策略 animSet.setDuration(5000); //播放动画 animSet.start();

组合动画示例

ObjectAnimator AlphaAnimator = ObjectAnimator.ofFloat(coverImageView, "alpha", 0.8f, 0f);
ObjectAnimator moveXAnimatior = ObjectAnimator.ofFloat(badgeImageView, "translationX",-100f);
ObjectAnimator moveYAnimatior = ObjectAnimator.ofFloat(badgeImageView, "translationY", -100f);
ObjectAnimator scaleX = ObjectAnimator.ofFloat(badgeImageView, "scaleX", 1f, 0.1f);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(badgeImageView, "scaleY", 1f, 0.1f);

AnimatorSet animSet = new AnimatorSet();
animSet.play(moveXAnimatior)
        .with(moveYAnimatior)
        .with(scaleX)
        .with(scaleY)
        .with(AlphaAnimator);

animSet.setDuration(3000);

//动画开始/结束/取消时的回调方法
animSet.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {

    }

    @Override
    public void onAnimationEnd(Animator animation) {
        badgeImageView.setVisibility(View.GONE);
        coverImageView.setVisibility(View.GONE);
    }

    @Override
    public void onAnimationCancel(Animator animation) {

    }

    @Override
    public void onAnimationRepeat(Animator animation) {

    }
});
animSet.start();

或者说在xml文件中定义动画集合

set_animation.xml

<set android:ordering="together" > 
    // 下面的动画同时进行 
    <objectAnimator 
        android:duration="2000" 
        android:propertyName="translationX" 
        android:valueFrom="0"
        android:valueTo="300"
        android:valueType="floatType" > 
    </objectAnimator>
    <objectAnimator 
        android:duration="3000" 
        android:propertyName="rotation"
        android:valueFrom="0" 
        android:valueTo="360" 
        android:valueType="floatType" > 
        </objectAnimator> 
</set>

使用动画集合

AnimatorSet animator = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set_animation);
animator.setTarget(targetView);
animator.start();

多重动画

第一个动画设置停止事件播放第二个动画

Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
        iv.startAnimation(animation);
        final Animation animation2 = AnimationUtils.loadAnimation(this, R.anim.rotate);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {

                iv.startAnimation(animation2);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

逐帧动画

使用方法

1.动画所用的图片导入res/drawable中

2.res/drawable创建动画定义文件

<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/m_1" android:duration="100" />
    <item android:drawable="@drawable/m_2" android:duration="100" />
    <item android:drawable="@drawable/m_3" android:duration="100" />
    <item android:drawable="@drawable/m_4" android:duration="100" />
    <item android:drawable="@drawable/m_5" android:duration="100" />
</animation-list>

3.Activity中使用

frameAnimImageView = (ImageView) findViewById(R.id.frame_anim);
    frameAnimImageView.setBackgroundResource(R.drawable.anim_frame);
    frameAnimImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            AnimationDrawable animationDrawable = (AnimationDrawable) frameAnimImageView.getBackground();
            animationDrawable.start();

        }
    });

LayoutAnimation

为ViewGroup指定的动画,当子元素展示的时候使用这个动画.常用在ListView上面.每个item出现的时候伴随着动画.

使用

在属性里直接定义

<ListView
    ...
    android:layoutAnimation:@anim/layout_anim01
    >

为PopupWindow添加动画

动画xml

wrap_slide_vertical_enter_in.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromYDelta="100%p"
        android:toYDelta="0%p"
        android:duration="200"
        android:fillAfter="true"
        />
</set>

wrap_slide_vertical_exit_out.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromYDelta="0%p"
        android:toYDelta="100%p"
        android:duration="200"
        android:fillAfter="true"
        />
</set>

设置Style

style.xml

<style name="popwindow_anim_style">
    <!-- 指定显示的动画xml -->
    <item name="android:windowEnterAnimation">@anim/wrap_slide_vertical_enter_in</item>
    <!-- 指定消失的动画xml -->
    <item name="android:windowExitAnimation">@anim/wrap_slide_vertical_exit_out</item>
</style>

PopupWindow设置动画

GoodsAttributePopup goodsAttributePopup = new GoodsAttributePopup(GoodsActivity.this, null, goods, attributes);
goodsAttributePopup.setAnimationStyle(R.style.popwindow_anim_style);
goodsAttributePopup.showAtLocation(rootView, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);