我爱编程

Android 动画

2017-10-29  本文已影响0人  笔墨Android

不怕跌倒,所以飞翔

Android动画分类

1.View动画

1.1 View动画有四种变换效果(对应这Animation的四个子类):

1.2 View动画的使用

1.2.1 XML方式使用动画

这里首先要说明一下创建的位置(一定是在res下面创建anim文件夹) : res/anim/XXX.xml

1.2.1.1整体的属性
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:interpolator="@android:anim/accelerate_decelerate_interpolator"
     android:shareInterpolator="true"/>

这个后面在仔细说....

1.2.1.2平移动画(对应TranslateAnimation类)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">

    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="0"
        android:toYDelta="0"
        />
</set>
1.2.1.3缩放动画(对应ScaleAnimation类)
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="false"
     android:interpolator="@android:anim/accelerate_decelerate_interpolator"
     android:shareInterpolator="true">

    <scale
        android:fromXScale="0"
        android:fromYScale="0"
        android:pivotX="0.5"
        android:pivotY="0.5"
        android:toXScale="1"
        android:toYScale="1"
        />
</set>

这里解释一下上面那段代码,就是从没有(因为是从0开始)到正常大小(这里的正常大小指的是原始尺寸),中心点要是"%"的话是指相对于自身控件的百分比但是如果要是"0.5"的话不代表"50%"而是指的是实际的像素点

1.2.1.4 旋转动画(对应RotateAnimation类)
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="5000"
     android:fillAfter="false"
     android:interpolator="@android:anim/accelerate_decelerate_interpolator"
     android:shareInterpolator="true">

    <rotate
        android:fromDegrees="0"
        android:pivotX="0.5"
        android:pivotY="0.5"
        android:toDegrees="359"/>
</set>
1.2.1.5 透明度动画 (对应AlphaAnimation)
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:duration="5000"
     android:fillAfter="false"
     android:interpolator="@android:anim/accelerate_decelerate_interpolator"
     android:shareInterpolator="true">

    <alpha
        android:fromAlpha="0.5"
        android:toAlpha="1"/>
</set>
1.2.1.6使用的代码:
        Animation translateAnimation = AnimationUtils.loadAnimation(this,R.anim.translate_animation);
        mIvAnimation.startAnimation(translateAnimation);

1.2.2 代码使用

        AlphaAnimation alphaAnimation = new AlphaAnimation(0,1);
        alphaAnimation.setDuration(500);
        mIvAnimation.setAnimation(alphaAnimation);

这里就举个例子其他的都差不多,看一眼传入得参数就好了...

1.3 帧动画(对应AnimationDrawable类)

帧动画是顺序播放一组预先定义好的动画,类似于电影播放.不同于View动画,系统提供另外一个类AnimationDrawable来使用帧动画,这里注意一点就是存放帧动画XML的位置res/drawable下面!!!

1.3.1 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/icon1"
        android:duration="500"/>
    <item
        android:drawable="@drawable/icon2"
        android:duration="500"/>
    <item
        android:drawable="@drawable/icon3"
        android:duration="500"/>
    <item
        android:drawable="@drawable/icon4"
        android:duration="500"/>
    <item
        android:drawable="@drawable/icon5"
        android:duration="500"/>
    <item
        android:drawable="@drawable/icon6"
        android:duration="500"/>
</animation-list>

1.3.2 代码使用

其实就是把上面定义的动画的XML当成背景设置到相应的ImageView上去,在通过getBackground取出来强转成AnimationDrawable调用start开启动画

        mIvFrame.setBackgroundResource(R.drawable.drawable_animation);
        AnimationDrawable animationDrawable = (AnimationDrawable) mIvFrame.getBackground();
        animationDrawable.start();

1.4 View动画的特殊使用场景

1.4.1 特殊使用场景

1.4.1.1 LayoutAnimation 为ViewGroup设置制定动画

这个的使用场景一般是直接作用在ViewGroup 常用在ListView或者RecycleView的条目上,从而为每个子View展示一些出场效果

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
                 android:animation="@anim/translate_animation"
                 android:animationOrder="normal"
                 android:delay="0.5"/>
android:layoutAnimation="@anim/item_layoutanimation"

就是在相应的ViewGroup控件中加上上面的属性标签就可以了

        Animation animation = AnimationUtils.loadAnimation(this, R.anim.XXX);
        LayoutAnimationController controller = new LayoutAnimationController(animation);
        controller.setDelay(0.5f);
        controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
        View.setLayoutAnimation(controller);
        View.startAnimation(animation);//这句是开始动画用的

这里注意一点就是XXX代表的是普通的动感,而不是layoutAnimation为根节点的动画!!!

1.4.1.2 Activity的切换效果

Activity有默认的切换效果,但是这个效果我们是可以自定义的,主要用到的是overridePendingTransition(int enterAnim, int exitAnim);这个方法要在startActivity(Intent)或者finish()之后调用才会生效

动画设置

Fragment可也可以添加切换动画,通过FragmentTransaction中的setCustomAnimations()方法来天机啊添加切换动画,这个切换动画需要时View动画,也可以是属性动画

2.属性动画

属性动画是API11添加的新特性,和View动画不同,它对作用的对象进行了扩展,属性动画可以对任何对象做动画,甚至还可以没有对象

2.1属性动画的使用

属性动画的默认时间间隔是300ms,默认的帧率是10ms/帧

2.1.1属性动画的常用类

2.1.2举例说明

ObjectAnimator.ofFloat(mIvAnimation, "translationY", mIvAnimation.getHeight()).setDuration(1000).start();
        ValueAnimator colorAnim = ObjectAnimator.ofInt(mRvBg, "backgroundColor", 0xffff8080, 0xff8080ff);
        colorAnim.setDuration(3000);
        colorAnim.setEvaluator(new ArgbEvaluator());/*设置估值器*/
        colorAnim.setRepeatCount(ValueAnimator.INFINITE);/*设置循环次数,这里是无限循环的*/
        colorAnim.setRepeatMode(ValueAnimator.REVERSE);/*设置循环模式-这里设置的是逆向模式*/
        colorAnim.start();
        AnimatorSet set = new AnimatorSet();
        set.playTogether(
                ObjectAnimator.ofFloat(mIvAnimation, "rotationX", 0, 360),//X轴旋转
                ObjectAnimator.ofFloat(mIvAnimation, "rotationY", 0, 180),//Y轴旋转
                ObjectAnimator.ofFloat(mIvAnimation, "rotation", 0, -90),//旋转
                ObjectAnimator.ofFloat(mIvAnimation, "translationX", 0, 90),//x轴平移
                ObjectAnimator.ofFloat(mIvAnimation, "translationY", 0, 90),//y轴平移
                ObjectAnimator.ofFloat(mIvAnimation, "scaleX", 1, 1.5f),//X轴缩放
                ObjectAnimator.ofFloat(mIvAnimation, "scaleY", 1, 0.5f),//Y轴缩放
                ObjectAnimator.ofFloat(mIvAnimation, "alpha", 1, 0.25f, 1)//渐变
        );
        set.setDuration(500).start();

2.1.2 XML使用属性动画(位置res/animator)

这做下说明:

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

    <objectAnimator
        android:duration="300"
        android:propertyName="x"
        android:valueTo="200"
        android:valueType="intType"/>

    <objectAnimator
        android:duration="300"
        android:propertyName="y"
        android:valueTo="200"
        android:valueType="intType"/>
</set>
        AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.animator_anim);
        set.setTarget(mIvAnimation);
        set.start();

2.2 插值器和估值器

2.3 属性动画的监听器

监听动画的播放过程,主要有如下两个接口 AnimatorUpdateListener,AnimatorListener

 public static interface AnimatorListener {
        void onAnimationStart(Animator animation);
        void onAnimationEnd(Animator animation);
        void onAnimationCancel(Animator animation);
        void onAnimationRepeat(Animator animation);
    }
public static interface AnimatorUpdateListener {
        void onAnimationUpdate(ValueAnimator animation);
    }

2.4对任意对象使用属性动画

任意对象使用属性动画必要条件:

针对于继承的View要使用属性动画的情况,官方给出了相应的解决方案:

/**
 * author :  贺金龙
 * create time : 2017/10/29 14:21
 * description : 包装类,为了向外面提供相应的get/set方法
 * instructions : 因为没有相应改变宽度和高度的方法,所以这里自己包装一个相应的get/set方法
 * version :
 */
public class ViewWrapper {
    private View mTargetView;


    /**
     * author :  贺金龙
     * create time : 2017/10/29 14:28
     * description : 传入相应的View,进行设置一些内容
     * instructions :
     * version :
     */
    public void setTargetView(View targetView) {
        mTargetView = targetView;
    }

    /**
     * author :  贺金龙
     * create time : 2017/10/29 14:30
     * description : 获取宽度的方法
     * instructions :
     * version :
     */
    public int getWidth() {
        return mTargetView.getLayoutParams().width;
    }

    /**
     * author :  贺金龙
     * create time : 2017/10/29 14:31
     * description : 设置宽度的方法
     * instructions : 设置相应的宽度
     * version :
     *
     * @param width 宽度
     */
    public void setWidth(int width) {
        mTargetView.getLayoutParams().width = width;
        /*重新绘制View的方法*/
        mTargetView.requestLayout();
    } 
}

***
//使用的代码
 ViewWrapper wrapper = new ViewWrapper();
 wrapper.setTargetView(view);
 ObjectAnimator.ofInt(wrapper, "width", 0, 500).setDuration(1000).start();

上面注释已经写的很详细了,说下大体的思路,传入一个View并通过LayoutParams设置相应的宽高,这样就相当于变相的设置了View的宽高了

        ValueAnimator valueAnimator = ValueAnimator.ofInt(0,500);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            /*持有一个整形的估值器*/
            private IntEvaluator mIntEvaluator = new IntEvaluator();

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                /*获取当前的动画值*/
                Integer animatedValue = (Integer) animation.getAnimatedValue();
                Log.e("done", "onAnimationUpdate: " + animatedValue);

                /*获取当前值占整个动画的比例,这个比例是0~1*/
                float animatedFraction = animation.getAnimatedFraction();

                view.getLayoutParams().width = mIntEvaluator.evaluate(animatedFraction, 0, 500);
                view.requestLayout();
            }
        });
        valueAnimator.setDuration(500);
        valueAnimator.start();

其实就是监听ValueAnimator的动画改变,用估值器进行数值的改变


2017年11月09日补充:

RevealAnimator动画效果

首先这个动画是在5.0以上的版本才能使用的

    public static Animator createCircularReveal(View view,
               int centerX,  int centerY, float startRadius, float endRadius) {
           return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
     }

[图片上传失败...(image-fc2cae-1510030864016)]

final View oval = this.findViewById(R.id.oval);  
oval.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Animator animator = ViewAnimationUtils.createCircularReveal(  
                oval,  
                oval.getWidth()/2,  
                oval.getHeight()/2,  
                oval.getWidth(),  
                0);  
        animator.setInterpolator(new AccelerateDecelerateInterpolator());  
        animator.setDuration(2000);  
        animator.start();  
    }  
});  
  
final View rect = this.findViewById(R.id.rect);  
rect.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
        Animator animator = ViewAnimationUtils.createCircularReveal(rect, 0, 0, 0,  (float) Math.hypot(rect.getWidth(), rect.getHeight()));  
        animator.setInterpolator(new AccelerateInterpolator());  
        animator.setDuration(2000);  
        animator.start();  
    }  
});  

其实这个动画和属性动画的写法基本上差不多,所以这里只是简单的实现了一些效果!

其实关于属性动画还有很多问题,这里面只是粗略的了解了一些皮毛......

上一篇 下一篇

猜你喜欢

热点阅读