Andoird 动画使用及知识点总结

183 阅读7分钟

Andorid动画类型

根据动画类型,我们可以将动画分为三大类:

  • 帧动画(drawable)

    • 可以理解为PPT放映,对预先排好序的drawable resource进行播放。
  • 补间动画(animation)

    • 只关心动画的开始与结束,其帧与帧之间的效果由动画本身决定,只有View能进行补间动画。
  • 属性动画(animator)

    • 简单点描述,就是通过不断的更改视图的属性,产生动画效果。

帧动画:

 1.在drawable下面放置好自己需要播放的drawable resource
 2.在drawable下面新建drawable_animation.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/drawable_01" android:duration="500"/>
            <item android:drawable="@drawable/drawable_02" android:duration="500"/>
            <item android:drawable="@drawable/drawable_03" android:duration="500"/>
    </animation-list>
//将声明好的drawable_animation.xml设置为对应view的background
binding.buttonDrawableAnimation.setBackground(AppCompatResources.getDrawable(getActivity(), 
        R.drawable.draweble_animation));
        
//使用AnimationDrawable对其进行播放
AnimationDrawable anim = (AnimationDrawable)binding.buttonDrawableAnimation.getBackground();
anim.start();

补间动画:

补间动画有四大类,分别为平移(translate)、缩放(scale)、透明度(alpha)、旋转(rotate)。
补间动画的实现,可以通过res/anim中新建对应的xml及代码中动态声明。
对于补间动画及差值器的实现,建议使用xml方式实现,这样可以提高复用也便于后期维护。
动画名称xml标签代码子类效果描述
平移动画translateTranslateAnimation对View进行X轴与Y轴的平移
缩放动画scaleScaleAnimation对View进行基于某个坐标的放大与缩小
透明度动画alphaAlphaAnimation对View进行透明度的改变
旋转动画rotateRotateAnimation对View进行基于某个坐标的旋转
  • 平移动画(translate)
  1. xml实现方式:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0%" android:fromYDelta="0%"
    android:toXDelta="50%" android:toYDelta="0%"
    android:fillAfter= "true"
    android:duration = "3000">
</translate>

<!-- 
fromXDelta 为translateX的起始点,百分比声明为以该控件的width为基准进行百分比计算,若直接声明数值,则为绝对数值。
fromYDelta 为translateY的起始点,百分比声明为以该控件的height为基准进行百分比计算,若直接声明数值,则为绝对数值。
toXDelta 为translateX的终点
toYDelta 为translateY的终点
fillAfter 为动画完成后,是否要以其最终属性填充
-->
  1. 代码实现方式: TranslateAnimation构造函数:
子类名参数参数含义
TranslateAnimationfromXTypeAnimation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT,声明X方向上translate是基于绝对数值,基于自身,基于父布局哪种Type.
fromXValuetranslateX的起始值
toXType同fromXType
toXValuetranslateX的终点值
fromYType同fromXType
fromYValuetranslateY的起始值
toYType同fromXType
toYValuetranslateY的终点值
//构造出,基于绝对位置,进行X右移 500, Y下移 500 的translate动画
TranslateAnimation translateAnimation = new TranslateAnimation(
        Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 500, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 500);
//设置动画时长
translateAnimation.setDuration(500);
//设置动画结束后,以最终属性填充控件位置
translateAnimation.setFillAfter(true);
//对应view播放该动画
view.startAnimation(translateAnimation);
  • 缩放动画(Scale):
  1. xml实现方式:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale = "100%" android:toXScale = "120%"
    android:fromYScale = "100%" android:toYScale = "120%"
    android:pivotX = "50%" android:pivotY = "50%"
    android:fillAfter = "true" android:duration = "500">

</scale>
<!-- fromXScale 为scaleX的初始值,百分比声明为以该控件的width为基准进行百分比计算
fromYScale 为scaleY的初始值,百分比声明为以该控件的height为基准进行百分比计算
toXScale 为scaleX的终点 
toYScale 为scaleY的终点 
fillAfter 为动画完成后,是否要以其最终属性填充 
上图动画效果则为,基于控件的中心点,控件原width height都扩大至1.2倍。
-->

2.代码实现方式:

ScaleAnimation构造函数:

子类名参数参数含义
ScaleAnimationfromX在动画开始时,该控件的水平方向起始值
toX动画结束时,该控件水平方向的最终值
fromY在动画开始时,该控件的垂直方向起始值
toY动画结束时,该控件的垂直方向的最终值
pivotXTypeAnimation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or Animation.RELATIVE_TO_PARENT,声明pivotXValue 是基于绝对数值、基于自身、基于父布局.
pivotXValue要缩放对象的点的X坐标,指定为绝对数,其中0是左边缘。(对象改变大小时,该点保持不变。)如果pivotXType为绝对值,则该值可以是绝对数,否则该值可以是百分比(其中1.0为100%)
pivotYType同上pivotXType,声明pivotYValue是基于什么类型
pivotYValue同上pivotXValue,为要缩放对象的点的Y坐标
//构造函数,基于view的 width * 0.5f, height * 0.5f 的中心点进行scale 1.5倍动画
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 1.5f, 1f, 1.5f,
        Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(1000);
scaleAnimation.setFillAfter(true);
view.startAnimation(scaleAnimation);
  • 透明度动画(Alpha):

1.xml实现方式:

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0" android:toAlpha="1"
    android:fillAfter = "true" android:duration = "500">

</alpha>
<!--
fromAlpha 透明度起始值
toAlpha  透明度最终值
0为透明 1为不透明
-->

2.代码实现方式:

AlphaAnimation构造函数:

子类名参数参数含义
AlphaAnimationfromAlpha透明度动画起始值
toAlpha透明度动画最终值
//构造函数,控件透明度由0f变化为1f
AlphaAnimation alphaAnimation = new AlphaAnimation(0f, 1f);
alphaAnimation.setDuration(2000);
alphaAnimation.setFillAfter(true);
view.setAnimation(alphaAnimation);
  • 旋转动画(rotate): 1.xml实现方式:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0" android:toDegrees="90"
    android:pivotX="50%" android:pivotY="50%"
    android:fillAfter = "true" android:duration = "2000">
</rotate>
<!--
fromDegrees 旋转角度起始值
toDegrees 旋转角度最终值
pivotX 旋转中心点X坐标
pivotY 旋转中心点Y坐标
-->

2.代码实现方式:

RotateAnimation 构造函数:

子类名参数参数含义
RotateAnimationfromDegrees旋转角度起始值
toDegrees旋转角度最终值
pivotXType设置pivotXValue基于绝对数值,自身,父布局类型
pivotXValue对象旋转所围绕的点的X坐标,指定为绝对数,其中0是左边缘。如果pivotXType为绝对值,则该值可以是绝对数,否则该值可以是百分比(其中1.0为100%)。
pivotYType设置pivotYValue基于绝对数值,自身,父布局类型
pivotYValue对象旋转所围绕的点的Y坐标,指定为绝对数,其中0是上边缘。如果pivotYType为绝对值,则该值可以是绝对数,否则该值可以是百分比(其中1.0为100%)。
//基于控件中心点,进行0-180度旋转
RotateAnimation rotateAnimation = new RotateAnimation(0f, 180f,
        Animation.RELATIVE_TO_SELF,
        0.5f, Animation.RELATIVE_TO_SELF,
        0.5f);
rotateAnimation.setFillAfter(true);
rotateAnimation.setDuration(2000);
view.setAniamtion(rotateAnimation);
  • AnimationListener

    对于动画的播放,我们可以通过animation.setAnimationListener进行监听

    animation.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {
        //动画播放前回调
    }
    
    @Override
    public void onAnimationEnd(Animation animation) {
        //动画结束前回调
    }
    
    @Override
    public void onAnimationRepeat(Animation animation) {
        //动画播放过程中回调
    }
    });
    

    我们可以根据对应的回调时机,去做一些业务或交互逻辑。

  • AnimationSet

    Set可以理解为集合,AnimationSet则为动画集合,可以将一系列的animation进行组装,然后进行统一播放,这样也可以实现较为复杂的动画交互。

    AnimationSet animationSet = new AnimationSet(true); //所有animation使用统一的差值器
    animationSet.addAnimation(rotateAnimation);
    animationSet.addAnimation(translateAnimation);
    animationSet.setFillAfter(true);
    animationSet.setDuration(2000); //ms
    view.startAnimation(animationSet);
    

    可以看到,我们可以通过animationSet给所有add进去的animation设置统一的duration, fillAfter等相关的动画属性。同样AnimationSet也可以添加AnimationListener去监听所有动画的播放情况。

  • 差值器:

    差值器的作用是定义动画的变化率,加速动画,减速动画,重复动画等。

    系统为我们提供了一系列默认的差值器类,这里举例几个,就不展开描述了。

    子类名xml id大致效果
    AccelerateDecelerateInterpolator@android:anim/accelerate_decelerate_interpolator动画始末速度较慢,动画中间过程加速
    CycleInterpolator@android:anim/cycle_interpolator循环播放速率改变为正弦曲线
    PathInterpolatornull定义路径坐标,按照路径坐标进行变化

    对于平常使用过程,PathInterpolator使用较多,一般该路径参数会由动效同事给出,我们需要按照动效同事给出的path参数,进行差值器构造。

    1.xml中构造(res/anim/path_interpolator.xml):

    <?xml version="1.0" encoding="utf-8"?>
    <pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
        android:controlX1="0.17"
        android:controlY1="0.51"
        android:controlX2="0.10"
        android:controlY2="1.00">
    
    </pathInterpolator>
    

    我们通过 xml中去将动效同事给出的path参数进行声明,然后在代码中进行读取设置。

    PathInterpolator pathInterpolator = (PathInterpolator)AnimationUtils
    .loadInterpolator(getContext(), R.anim.translate_animation);
    animationSet.setInterpolator(pathInterpolator);
    

属性动画:

属性动画(Animator)的几个常用子类

  • ValueAnimator

    只关心传入的数据变化区间,而不关心具体是做什么属性变化的动画,需要通过AnimatorUpdateListener的回调,动态接收回调中传回的数值,自己对相关视图的属性进行修改。

   ofFloat float类型数据变化
   ofArgb argb数据变化
   ofInt int类型数据变化
   ofObject 自定义数据类型变化
   
  其大致工作流程:
  ofInt(0, 100)---->差值器---->数值计算--->updateListene数值返回---->控件属性修改
  定义数值变化区间 -> 当前数值 -> 计算后的数值 -> 当前数值通过监听器返回给调用 -> 监听回调设置控件属性变化
  • ObjectAnimator: 构造函数:

    public static ObjectAnimator ofFloat(Object target, String propertyName, float… values)

    public static ObjectAnimator ofInt(Object target, String propertyName, float… values)

    通过我们传入的propertyName(属性名称),其内部会通过该属性名称去寻找target对应的该属性的set/get方法,然后去修改target的对应属性。

//透明度变化 1 -> 0 -> 1
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha",1 , 0, 1);  
animator.setDuration(500);  
animator.start(); 

//围绕x轴旋转 0 -> 90 -> 270
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationX", 0,90 ,270);  
animator.setDuration(500);  
animator.start();

//围绕y轴旋转 0 -> 90 -> 270
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 0,90 ,270);  
animator.setDuration(500);  
animator.start();

//围绕z轴旋转 0 -> 90 -> 270
ObjectAnimator animator = ObjectAnimator.ofFloat(view,"rotation", 0 ,90 ,270);  
animator.setDuration(500);  
animator.start();  

//在x轴上平移 0 -> 100 -> -100 -> 0
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 0, 100, -100, 0);  
animator.setDuration(500);  
animator.start(); 

//在y轴上平移 0 -> 100 -> -100 -> 0
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationY", 0, 100, -100, 0);  
animator.setDuration(500);  
animator.start(); 

//在x轴缩放 0.5 -> 1.2 -> 1
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 0.5f, 1.2f, 1f);  
animator.setDuration(500);  
animator.start();

//在y轴上缩放 0.5 -> 1.2 -> 1
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleY", 0.5f, 1.2f, 1f);  
animator.setDuration(500);  
animator.start(); 
  • AnimatorSet:

    AnimatorSet与AnimationSet类似,可以将多个Animtor动画进行组合播放

函数名效果调用
playTogether()同时播放多个animtorplayTogether(animator1, animator2 ...)
play()播放传入的animtor,并返回Budilerplay(animator1)
play().with()播放传入的animator,并同时播放with传入的play(anim1).with(anim2)
play().before()播放传入的animator,并在前面插入一段animatorplay(anim1).before(anim2)
play().after()播放传入的animator,并在结束后插入一段animatorplay(anim2).after(anim2)
  • 差值器:

    其含义与上面的animation差值器类似,此处不做过多说明

  • xml实现动画 :

<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially" >
    <set android:ordering="together" >
    <objectAnimator
        android:duration="1000"
        android:propertyName="translationX"
        android:valueFrom="-0"
        android:valueTo="100"
        android:valueType="floatType" >
    </objectAnimator>
        <objectAnimator
            android:duration="1000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" >
        </objectAnimator>
        <set android:ordering="together" >
            <objectAnimator
                android:duration="1000"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" >
            </objectAnimator>
            <objectAnimator
                android:duration="1000"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" >
            </objectAnimator>
        </set>
    </set>
</set>

xml的使用:

Animator animator = AnimatorInflater.loadAnimator(getActivity(), R.anim.translate_animation);
animator.setTarget(buttonView);
animator.start();