Android 动画

Android 动画主要分来两类:
1.tweeted 动画 , 补间动画
2.frame 动画,   逐帧动画

首先来说说简单的  frame by frame 动画, 这个动画实现起来很简单,
但是在Android上用的不是很多, 我遇到的是在一些复杂的loading 动画时候用到
frame 动画  同样可以定义在Xml中, 同样也可以在代码中写

下面是在xml顶一个一个动画

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
                android:oneshot="false">
    <!-- android:oneshot
        如果为false 表示重复播放
        如果为true 表示只播放一遍
    -->

    <item
        android:drawable="@drawable/loading_1"
        android:duration="60"/>
    <!-- 每一个item 表示一帧-->
    <item
        android:drawable="@drawable/loading_2"
        android:duration="60"/>
    <item
        android:drawable="@drawable/loading_3"
        android:duration="60"/>
    <item
        android:drawable="@drawable/loading_4"
        android:duration="60"/>
    <item
        android:drawable="@drawable/loading_5"
        android:duration="60"/>
    <item
        android:drawable="@drawable/loading_6"
        android:duration="60"/>
    <item
        android:drawable="@drawable/loading_7"
        android:duration="60"/>
    <item
        android:drawable="@drawable/loading_8"
        android:duration="60"/>

</animation-list>

当如果吧这个动画放在一个View上作为载体的画, 那上面的动画文件就需要放在 drawable文件夹下面了.

mImageView = (ImageView) findViewById(R.id.img);
mImageView.setBackgroundResource(R.drawable.loading);
mLoadingAnim = (AnimationDrawable) mImageView.getBackground();

如上代码所示, 通过ImageView 去加载动画, 获取到 mLoadingAnim 后可以控制动画了,

需要注意的是, 为了确保 动画里的每一帧不被自适应放大, 那么就 最好吧每一帧的图片放到 drawable-xxhpi文件夹中去, 
这一问题是在为ProgressBar设置动画时 遇到的,
Progress设置动画如下:
<ProgressBar
    android:id="@+id/progress_bar"
    android:layout_width="28dp"
    android:layout_height="28dp"
    android:indeterminate="true"
    android:indeterminateDrawable="@anim/loading"
    />
这里之前把动画的图片放到 drawable文件下发现怎么设宽高都会有问题, 现在把它放到  drawable-xxhpi 就好了 ,可以设置款到为28dp, 即这张图片的真是宽高,  
但是还有一个问题就是, 我设置成  宽高wrap_content 还是会有问题, 这个问题下次整理ProgressBar的时候在做处理.

下面在来看看 用代码来实现
mLoadingAnim = new AnimationDrawable();
for (int i = 1; i <= 8; i++) {
    int id = getResources().getIdentifier("loading_" + i, "drawable", getPackageName());
    Drawable drawable = getResources().getDrawable(id);
    mLoadingAnim.addFrame(drawable, 60);
}
mLoadingAnim.setOneShot(false);
mImageView.setBackgroundDrawable(mLoadingAnim);

ok 上面大致了解一下 逐帧动画的基本用法了

下面在来看看 tweeted 动画

动画的属性有:
alpha           渐变透明度动画效果
scale           渐变尺寸伸缩动画效果
translate      画面转换位置移动动画效果
rotate          画面转移旋转动画效果
下面看看在xml 定义这些动画,
Alpha
<?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="3000"
/> 
<!-- 透明度控制动画效果 alpha
        浮点型值:
            fromAlpha 属性为动画起始时透明度
            toAlpha   属性为动画结束时透明度
            说明: 
                0.0表示完全透明
                1.0表示完全不透明
            以上值取0.0-1.0之间的float数据类型的数字

        长整型值:
            duration  属性为动画持续时间
            说明:     
                时间以毫秒为单位
-->
</set>
Scale
<?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.4"
          android:fromYScale="0.0"
          android:toYScale="1.4"
          android:pivotX="50%"
          android:pivotY="50%"
          android:fillAfter="false"
          android:duration="700" />
</set>
<!-- 尺寸伸缩动画效果 scale
       属性:interpolator 指定一个动画的插入器
        在我试验过程中,使用android.res.anim中的资源时候发现
        有三种动画插入器:
            accelerate_decelerate_interpolator  加速-减速 动画插入器
            accelerate_interpolator        	加速-动画插入器
            decelerate_interpolator        	减速- 动画插入器
        其他的属于特定的动画效果
      浮点型值:
         
            fromXScale 属性为动画起始时 X坐标上的伸缩尺寸    
            toXScale   属性为动画结束时 X坐标上的伸缩尺寸     
        
            fromYScale 属性为动画起始时Y坐标上的伸缩尺寸    
            toYScale   属性为动画结束时Y坐标上的伸缩尺寸    
        
            说明:
                 以上四种属性值    
    
                    0.0表示收缩到没有 
                    1.0表示正常无伸缩     
                    值小于1.0表示收缩  
                    值大于1.0表示放大
        
            pivotX     属性为动画相对于物件的X坐标的开始位置
            pivotY     属性为动画相对于物件的Y坐标的开始位置
        
            说明:
                    以上两个属性值 从0%-100%中取值
                    50%为物件的X或Y方向坐标上的中点位置
        
        长整型值:
            duration  属性为动画持续时间
            说明:   时间以毫秒为单位

        布尔型值:
            fillAfter 属性 当设置为true ,该动画转化在动画结束后被应用
-->
Translate
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="30"
android:toXDelta="-80"
android:fromYDelta="30"
android:toYDelta="300"
android:duration="2000"
/>
<!-- translate 位置转移动画效果
        整型值:
            fromXDelta 属性为动画起始时 X坐标上的位置    
            toXDelta   属性为动画结束时 X坐标上的位置
            fromYDelta 属性为动画起始时 Y坐标上的位置
            toYDelta   属性为动画结束时 Y坐标上的位置
            注意:
                     没有指定fromXType toXType fromYType toYType 时候,
                     默认是以自己为相对参照物             
        长整型值:
            duration  属性为动画持续时间
            说明:   时间以毫秒为单位
-->
</set>
Rotate
<?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="+350"         
        android:pivotX="50%" 
        android:pivotY="50%"     
        android:duration="3000" />  
<!-- rotate 旋转动画效果
       属性:interpolator 指定一个动画的插入器
             在我试验过程中,使用android.res.anim中的资源时候发现
             有三种动画插入器:
                accelerate_decelerate_interpolator   	加速-减速 动画插入器
                accelerate_interpolator               	加速-动画插入器
                decelerate_interpolator               	减速- 动画插入器
             其他的属于特定的动画效果

       浮点数型值:
            fromDegrees 属性为动画起始时物件的角度    
            toDegrees   属性为动画结束时物件旋转的角度 可以大于360度   


            说明:
                     当角度为负数——表示逆时针旋转
                     当角度为正数——表示顺时针旋转              
                     (负数from——to正数:顺时针旋转)   
                     (负数from——to负数:逆时针旋转) 
                     (正数from——to正数:顺时针旋转) 
                     (正数from——to负数:逆时针旋转)       

            pivotX     属性为动画相对于物件的X坐标的开始位置
            pivotY     属性为动画相对于物件的Y坐标的开始位置

            说明:        以上两个属性值 从0%-100%中取值
                         50%为物件的X或Y方向坐标上的中点位置

        长整型值:
            duration  属性为动画持续时间
            说明:       时间以毫秒为单位
-->
</set>
接下来看如何使用这些动画
alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha);
mImageView.startAnimation(alphaAnimation);
先加载处动画, 然后在适当的时候调用view 的startAnimation 就可以执行动画了.
这样的动画有一个问题就是,  当动画结束后,不会改变View本身的任何属性,
比如说, 我们设定动画结束的alpha 是0.1  那么当动画结束之后view 有变成了原来的熟悉了

所以为了能让动画,在结束后保留相关的属性, 就引入了属性动画:
用例如下: 
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "Alpha", mImageView.getAlpha(), 0.1f);
mObjectAnimator.setDuration(3000);
mObjectAnimator.start();
上面是一个改编透明度的动画
还有一些其他属性的相关动画 如下: 
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", mImageView.getTranslationX(), 200);
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "translationY", mImageView.getTranslationY(), 200);
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleX", mImageView.getScaleX(), 0.1f);
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleY", mImageView.getScaleY(), 0.1f);
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "rotationX", mImageView.getRotationX(), 300);
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "rotationY", mImageView.getRotationY(), 300);
mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "rotation", mImageView.getRotation(), 300);
同时我还可以手动的设置这些View 这些属性:
mImageView.setAlpha(1.0f);
mImageView.setTranslationX(0);
mImageView.setTranslationY(0);
mImageView.setScaleX(1);
mImageView.setScaleY(1);
mImageView.setRotation(1);
mImageView.setRotationX(0);
mImageView.setRotationY(0);
在使用 scale 和rotation 动画时需要注意设置
缩放 与旋转的相对点
mImageView.setPivotX(0);
mImageView.setPivotX(0);
默认是View 的中心点, 里面的设置的值 是相对View 的左上角定点开始的

其实一些复杂的动画 就是多种动画组合在一起完成的,
下面就是多个动画一起执行的例子 
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(duration);
animatorSet.playTogether(topLineAnim, bottomLineAnim);
animatorSet.setInterpolator(new OvershootInterpolator(1.5f));
animatorSet.start();
只要 在animatorSet de playTogether 方法中加入一起执行的 ObjectAnimator就可以了

对了说道动画, 就还要讲一讲插值器, 上面的setInterpolator 方法就是色值插值器
关于插值器的可以查看一下几篇文章
介绍 几种基本的插值器

介绍生成插值器的方法

动画的过程是可以监听的: 
animatorSet.addListener(new Animator.AnimatorListener() {

    @Override
    public void onAnimationStart(Animator animation) {
    }

    @Override
    public void onAnimationRepeat(Animator animation) {

    }

    @Override
    public void onAnimationEnd(Animator animation) {
        mIsStartingDateTransAnimation = false;
    }

    @Override
    public void onAnimationCancel(Animator animation) {

    }
});
可以更具自己的需要重载一些方法,
这里需要注意的是,
在调用 AnimSet.cancel() 取消动画的时候
AnimatorListener 会回调 onAnimationEnd 和 onAnimationCancel
动画正常结束 只会调用 onAnimationEnd 方法.

mObjectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleX", mImageView.getScaleX(), 0.1f)
除了以上这种构建属性动画的方式 还下面一种 
PropertyValuesHolder pvhAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 0, 1);
PropertyValuesHolder pvhTransY = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, tipsTxt.getMeasuredHeight() * 2 / 3, 0);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(tipsTxt, pvhAlpha, pvhTransY);
animator.setDuration(450);
animator.start();

部分内容参考 

http://blog.youkuaiyun.com/ithomer/article/details/7523328


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值