Android动画

View动画

View动画的对象是View,View动画只改变View的显示,并不影响View的响应区域。它支持四种动画:TranslateAnimation、ScaleAnimation、AlphaAnimation、RotateAnimation。使用方式如下所示:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"----动画集合,对应AnimationSet类
    android:shareInterpolator="true"----动画集合内的动画是否共用插值器
    android:duration="500"----动画时间
    android:fillAfter="true"------动画结束后是否保持动画结束后的状态>
    <translate---------平移动画,对应TranslateAnimation
        android:fromXDelta="0"-----移动起始点的x坐标,相对于View左边界的距离
        android:fromYDelta="0"-----移动起始点的y坐标,相对于View上边界的距离
        android:toXDelta="100"-----移动结束点的x坐标,相对于View左边界的距离
        android:toYDelta="100"-----移动结束点的y坐标,相对于View上边界的距离
         />
	<!--translate动画的四个属性数据类型均为float或者percent,有三种表现形式:
	1、相对于View的左/上边距,单位为像素值(如"10")
	2、相对于View的左/上边距与View宽/高度的百分比(如"5%")
	3、相对于View的左/上边距与View父容器的宽/高度的百分比(如"5%p")-->

    <rotate------旋转动画,对应RotateAnimation
        android:fromDegrees="0"----旋转的初始角度(float)
        android:pivotX="0.5"----旋转中心点x坐标(float、percent),表现形式同平移动画属性
        android:pivotY="0.5"----旋转中心点y坐标(float、percent),表现形式同平移动画属性
        android:toDegrees="360"----旋转的结束角度(float)
         />

    <scale----缩放动画,对应ScaleAnimation
        android:fromXScale="1"----水平方向缩放比初始值(float),1表示原始大小
        android:fromYScale="1"----竖直方向缩放比初始值(float),1表示原始大小
        android:pivotX="0.5"----缩放中心点x坐标(float)
        android:pivotY="0.5"----缩放中心点y坐标(float)
        android:toXScale="1.5"----水平方向缩放比最终值(float)
        android:toYScale="1.5"----竖直方向缩放比最终值(float)
         />

    <alpha----透明度动画,对应AlphaAnimation
        android:fromAlpha="1"----动画初始透明度(float),1为不透明,0为完全透明
        android:toAlpha="0"----动画最终透明度(float)
        />
</set>

然后在代码中通过如下方式即可实现动画效果:

ImageView imageView=findViewById(R.id.iv_animate_view);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.view_anim);
imageView.setAnimation(animation);
animation.start();

当然,也可以在代码中使用View动画,但对于View动画来说,建议采用XML的方式来定义动画。

 //在代码中使用View动画
AlphaAnimation alphaAnimation=new AlphaAnimation(0,1);
alphaAnimation.setFillAfter(true);
alphaAnimation.setDuration(1000);
imageView.setAnimation(alphaAnimation);
alphaAnimation.start();

另外,通过Animation的setAnimationListener方法可以给View动画添加监听:

public static interface AnimationListener {
        void onAnimationStart(Animation animation);
        void onAnimationEnd(Animation animation);
        void onAnimationRepeat(Animation animation);
    }
View动画的特殊使用场景
使用LayoutAnimation为ViewGroup的子View添加入场动画

在xml中定义LayoutAnimation

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@anim/slide_from_right"----为元素指定具体的入场动画
    android:animationOrder="normal"----元素动画的顺序,normal表示顺序显示,reverse表示反序显示,random表示随机显示
    android:delay="10%" ----表示子元素开始动画的时间延迟
    />

LayoutAnimation在代码中可以通过下面代码的方式进行使用

LayoutAnimationController layoutAnimationController =
                AnimationUtils.loadLayoutAnimation(this, R.anim.layout_animation_slide_from_right);
        recyclerView.setLayoutAnimation(layoutAnimationController);

也可以在xml文件中进行使用,代码如下

 <android.support.v7.widget.RecyclerView
        android:id="@+id/rlv_layout_anim"
        android:layoutAnimation="@anim/layout_animation_slide_from_right"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
Activity的切换效果

Activity可以通过overridePendingTransiton(int enterAnim , int exitAnim)方法来自定义Activity的切换动画,这个方法必须在startActivity(intent)方法或者finish()方法之后被调用才能生效,其中enterAnim表示Activity被打开时的动画资源,exitAnim表示Activity退出时的动画资源。Fragment也可以通过setCustomerAnimations()的方法来添加切换动画。

drawable动画(帧动画)

帧动画是一组图片按照一定的顺序和时间间隔逐张切换的动画,不同于补间动画,帧动画的xml文件是放在drawable文件夹下的,其用法如下所示:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true"---是否播放一次,true表示播放一次,false表示循环播放>
    <item
        android:drawable="@drawable/bao1"---对应帧的资源图片
        android:duration="300"---对应帧的显示时间 />
    <item
        android:drawable="@drawable/bao2"
        android:duration="300" />
    <item
        android:drawable="@drawable/bao3"
        android:duration="300" />
    <item
        android:drawable="@drawable/bao4"
        android:duration="300" />
    <item
        android:drawable="@drawable/bao5"
        android:duration="300" />
    <item
        android:drawable="@drawable/bao6"
        android:duration="300" />
    <item
        android:drawable="@drawable/bao7"
        android:duration="300" />
    <item
        android:drawable="@drawable/bao8"
        android:duration="300" />

</animation-list>

然后可以在代码中使用:

imageView.setImageResource(R.drawable.drawable_anim);
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
animationDrawable.start();

当然,也可已在代码中定义帧动画,代码如下:

AnimationDrawable animationDrawable1=new AnimationDrawable();
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao1),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao2),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao3),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao4),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao5),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao6),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao7),50);
animationDrawable1.addFrame(getResources().getDrawable(R.drawable.bao8),50);
animationDrawable1.setOneShot(false);
imageView.setImageDrawable(animationDrawable1);
animationDrawable1.start();

在使用帧动画的时候要特别注意内存溢出的问题,因此,在使用帧动画的时候应当尽量避免使用过多尺寸较大的图片。

属性动画

属性动画不仅可以作用于View,它可以对任何对象做动画,甚至可以没有对象。在这里,需要知道一些属性动画中插值器(Interpolator)与估值器(TypeEvaluator)的相关知识。

  • TimeInterpolator(时间插值器):它的作用是根据时间流逝的百分比计算出当前属性值改变的百分比,系统预置的有LinearInterpolator(线性插值器:匀速)、AccelerateDecelerateInterpolator(加速减速插值器)和DecelerateInterpolator(减速插值器)等。
  • TypeEvaluator(类型估值器):它的作用是根据当前属性改变的百分比来计算改变后的属性值,系统预置的有IntEvaluator(针对整型属性)、FloatEvaluator(针对浮点型属性)、和ArgbEvaluator(针对Color属性)。

在xml中定义属性动画:

<?xml version="1.0" encoding="utf-8"?>
<set ----对应AnimatorSet
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together"----表示集合中子动画的播放次序,together表示同时播放,sequentially表示次序播放
    >
    <objectAnimator----对应ObjectAnimator
        android:propertyName="x"----表示作用对象的属性名称,string
        android:duration="300"----表示动画时长,int
        android:valueFrom="0"----表示属性起始值,int|float|color
        android:valueTo="200"----表示属性结束值,int|float|color
        android:startOffset="0"----表示动画延迟多少毫秒后开始播放,int
        android:repeatCount="0"----表示动画重复次数,默认为0,-1表示无限循环,int
        android:repeatMode="restart"----表示动画的重复模式,restart表示连续重复,reverse表示逆向重复
        android:valueType="intType"----表示属性的类型,有intType和floatType两个选项,若为颜色属性则无需指定,系统会自动处理
         />

    <animator----对应ValueAnimator,对应属性同objectAnimator,为objectAnimator直接父类,无propertyName属性
        android:duration="300"
        android:valueFrom="0"
        android:valueTo="200"
        android:startOffset="0"
        android:repeatCount="1"
        android:repeatMode="restart"
        android:valueType="intType" />
</set>

可以在代码中通过如下方式使用上面的属性动画:

AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.anim.property_anim);
animatorSet.setTarget(iv);
animatorSet.start();

也可以在代码中动态创建使用属性动画,代码如下:

 ObjectAnimator objectAnimator=
                ObjectAnimator.ofInt(iv,"x",0,200).setDuration(1000);
 objectAnimator.start();
对任意属性做动画

对object的属性做动画,需要同时满足两个条件:

  • object必须要提供setAbc方法,如果动画的时候没有传递初始值,那么还要提供getAbc方法,因为系统要去取abc属性的初始值(如果这条不满足,程序直接crash)。

  • object的setAbc 对属性abc所做的改变必须能够通过某种方法反映出来,比如会带来ui改变之类的(如果这条不满足,动画无效但不会crash)。
    当动画无法满足上述条件时,动画无法生效,此时有如下三种解决方法:

  • 如果你有权限的话,给你的对象加上get和set方法。

  • 用一个类来包装原始对象,间接为其提供get和set方法。

 ViewWrapper wrapper = new ViewWrapper(iv);
ObjectAnimator objectAnimator =
                ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(1000);
 objectAnimator.start();

private static class ViewWrapper {
        private View view;

        public ViewWrapper(View view) {
            this.view = view;
        }

        public int getWidth() {
            return view.getLayoutParams().width;
        }

        public void setWidth(int width) {
            view.getLayoutParams().width = width;
            view.requestLayout();
        }
    }
  • 采用ValueAnimator,监听动画过程,自己实现属性的改变
private void performAnimate(final View target, final int start, final int end) {
        //持有一个IntEvaluator对象,方便下面估值使用
        ValueAnimator valueAnimator = ValueAnimator.ofInt(1, 100);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            private IntEvaluator intEvaluator = new IntEvaluator();

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //获得当前进度占整个动画过程的比例,浮点型,0-1之间
                float fraction = animation.getAnimatedFraction();
                //直接调用整型估值器,通过比例计算出宽度,然后设置给Button
                target.getLayoutParams().width = intEvaluator.evaluate(fraction, start, end);
                target.requestLayout();
            }
        });
        valueAnimator.setDuration(5000).start();
    }
属性动画常用的特殊场景

属性动画可以为ViewGroup的子View的显示和隐藏设置过渡动画。Android系统中已经提供了默认过渡动画(在layout文件中将ViewGroup的animaiteLayoutChanges属性打开就可以使用系统提供的默认过渡动画)。Android系统中提供了如下所示的4种类型的过渡动画:

  • APPERING——当通过设置子View的可见性为VISIBLE或者通过addView方法添加子View来显示子View时,子View就会执行该类型的动画。
  • DISAPEARING——通过设置子View的可见性为GONE或者通过removeView方法移除子View时,子View会执行该类型动画。
  • CHANGE_APPEARING——当显示子View时,所有的兄弟view就会依次执行该类型动画,且兄弟View之间执行动画间隙默认为0毫秒,然后才会执行显示子View的动画。该类型动画的周期为300毫秒,默认延迟为0毫秒。
  • CHANGE_DISAPERING——当隐藏子View的动画执行完毕后,所有的兄弟View就会依次执行该类型动画且兄弟View之间执行动画间隙默认为0毫秒。该类型动画的周期为300毫秒,默认延迟为300毫秒。
    若觉得Android系统提供的过渡动画不够炫,也可以自定义过渡动画:
		LayoutTransition transition = new LayoutTransition();
        //当多个子View要执行同一个类型的动画时,就可以通过该方法来设置子View之间执行动画的间隙默认为0毫秒。
        transition.setStagger(LayoutTransition.CHANGE_APPEARING, 30);
        //为指定类型的过渡动画设置执行动画的周期,默认为300毫秒。
        transition.setDuration(LayoutTransition.CHANGE_APPEARING, transition.getDuration(LayoutTransition.CHANGE_APPEARING));
        //为指定类型的过渡动画设置延迟执行的时间,默认与过渡动画的类型相关
        transition.setStartDelay(LayoutTransition.CHANGE_APPEARING, 0);
        ObjectAnimator appearingAnimator = ObjectAnimator.ofPropertyValuesHolder((Object) null,
                PropertyValuesHolder.ofFloat("scaleX", 0.0f, 1.0f),
                PropertyValuesHolder.ofFloat("scaleY", 0.0f, 1.0f),
                PropertyValuesHolder.ofFloat("alpha", 0.0f, 1.0f));
        transition.setAnimator(LayoutTransition.APPEARING, appearingAnimator);
        transition.setDuration(LayoutTransition.APPEARING, transition.getDuration(LayoutTransition.APPEARING));
        transition.setStartDelay(LayoutTransition.APPEARING, transition.getDuration(LayoutTransition.CHANGE_APPEARING));

        ObjectAnimator disappearingAnimator =  ObjectAnimator.ofPropertyValuesHolder((Object) null,
                PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.0f),
                PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.0f),
                PropertyValuesHolder.ofFloat("alpha", 1.0f, 0));
        transition.setAnimator(LayoutTransition.DISAPPEARING, disappearingAnimator);
        transition.setDuration(LayoutTransition.DISAPPEARING, transition.getDuration(LayoutTransition.DISAPPEARING));
        transition.setStartDelay(LayoutTransition.DISAPPEARING, 0);

        transition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30);
        transition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, transition.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
        transition.setStartDelay(LayoutTransition.CHANGE_DISAPPEARING, transition.getDuration(LayoutTransition.DISAPPEARING));
        //为ViewGroup设置过渡动画。
        llImage.setLayoutTransition(transition);

参考资料:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值