Android开发艺术探索__android动画深入分析(七)

来源:互联网 发布:windows c盘清理 编辑:程序博客网 时间:2024/05/09 04:37

分类

Android的动画可以分为三种:1.View动画,也叫补间动画(Tween Animation)2.帧动画,也叫逐帧动画(Frame Animation)3.属性动画

View动画

View动画的作用对象是View,分为四种:

静态创建:

创建文件夹>>右键整个module,创建resource direct,选择xml格式,名为anim<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"    android:interpolator="@[package:]anim/interpolator_resource"     android:shareInterpolator="true"     android:duration="3000"     android:fillAfter="true">    //子类也有duration    <alpha android:fromAlpha="0"           android:toAlpha="0.8"/>    <scale android:fromXScale="0"           android:fromYScale="0"           android:pivotX="50"           android:pivotY="50"           android:toXScale="1"           android:toYScale="1"/>    <rotate android:fromDegrees="0"            android:pivotX="50"            android:pivotY="50"            android:toDegrees="360"/>    <translate android:fromXDelta="0"               android:fromYDelta="0"               android:toXDelta="100"               android:toYDelta="100"/></set>
android:interpolator:插值器,默认为#android:anim/accelerate_decelerate_interpolarandroid:shareInterpolator:是否共享插值器andorid:fillAtler:动画结束后画面是否停留在最后一刻的位置andorid:fillAtler:fillBefore:动画结束后是否停留在动画的第一帧
在代码中开始动画:    public void test(View view) {    //使用AnimationUtils.loadAnimation(context,R.anim.xxx)来将静态动画加载进入代码        Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation);        btn.startAnimation(animation);    }

动态创建动画

        //单个动画        ScaleAnimation scaleAnimation = new ScaleAnimation(0f,1f,0f,1f        ,btn.getWidth()/2,btn.getHeight()/2);        scaleAnimation.setDuration(1000);        btn.startAnimation(scaleAnimation);        //动画组合        AnimationSet animationSet = new AnimationSet(false);        animationSet.addAnimation(scaleAnimation);        animationSet.setDuration(1000);        btn.startAnimation(animationSet);

设置补间动画的监听器

    //设置监听器    private void addAnimationListener(Animation animation) {        animation.setAnimationListener(new Animation.AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {            }            @Override            public void onAnimationEnd(Animation animation) {            }            @Override            public void onAnimationRepeat(Animation animation) {            }        });    }

自定义补间动画

自定义补间动画说难不难,说简单不简单,因为这主要是数学的应用;继承Animation这个类,实现initialize(),在里面做一些初始化操作实现applyTransformation(),在里面进行矩阵的变换,可以利用Camera来简化矩阵变化你的过程
3D的旋转效果demo:package com.example.android.apis.animation;import android.view.animation.Animation;import android.view.animation.Transformation;import android.graphics.Camera;import android.graphics.Matrix;/** * An animation that rotates the view on the Y axis between two specified angles. * This animation also adds a translation on the Z axis (depth) to improve the effect. */public class Rotate3dAnimation extends Animation {    private final float mFromDegrees;    private final float mToDegrees;    private final float mCenterX;    private final float mCenterY;    private final float mDepthZ;    private final boolean mReverse;    private Camera mCamera;    /**     * Creates a new 3D rotation on the Y axis. The rotation is defined by its     * start angle and its end angle. Both angles are in degrees. The rotation     * is performed around a center point on the 2D space, definied by a pair     * of X and Y coordinates, called centerX and centerY. When the animation     * starts, a translation on the Z axis (depth) is performed. The length     * of the translation can be specified, as well as whether the translation     * should be reversed in time.     *     * @param fromDegrees the start angle of the 3D rotation     * @param toDegrees the end angle of the 3D rotation     * @param centerX the X center of the 3D rotation     * @param centerY the Y center of the 3D rotation     * @param reverse true if the translation should be reversed, false otherwise     */    public Rotate3dAnimation(float fromDegrees, float toDegrees,            float centerX, float centerY, float depthZ, boolean reverse) {        mFromDegrees = fromDegrees;        mToDegrees = toDegrees;        mCenterX = centerX;        mCenterY = centerY;        mDepthZ = depthZ;        mReverse = reverse;    }    @Override    public void initialize(int width, int height, int parentWidth, int parentHeight) {        super.initialize(width, height, parentWidth, parentHeight);        mCamera = new Camera();    }    @Override    protected void applyTransformation(float interpolatedTime, Transformation t) {        final float fromDegrees = mFromDegrees;        float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);        final float centerX = mCenterX;        final float centerY = mCenterY;        final Camera camera = mCamera;        final Matrix matrix = t.getMatrix();        camera.save();        if (mReverse) {            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);        } else {            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));        }        camera.rotateY(degrees);        camera.getMatrix(matrix);        camera.restore();        matrix.preTranslate(-centerX, -centerY);        matrix.postTranslate(centerX, centerY);    }}

帧动画

参考动漫,动态的画面是由多张静态的画面在单位时间内连续变换而产生的动画效果,本质上也是view动画的一种;

使用方法

在res/drawable中创建一个xml文件,以animation-list为根元素<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="false"> //是否只使用一次,false则会不停的循环    <item android:drawable="@drawable/frame_animation_1" android:duration="1000"/>    <item android:drawable="@drawable/frame_animatiion_2" android:duration="1000"/>    <item android:drawable="@drawable/frame_animation_1" android:duration="1000"/>    <item android:drawable="@drawable/frame_animatiion_2" android:duration="1000"/></animation-list>
    public void test(View view) {        btn.setBackgroundResource(R.drawable.frame_animation);        AnimationDrawable animationDrawable = (AnimationDrawable) btn.getBackground();        animationDrawable.start();    }

View动画的使用场景:作为Viewgroup中子元素的出场动画

静态使用

在drawable中创建xml文件,<layoutAnimation    xmlns:android="http://schemas.android.com/apk/res/android"    android:animation="@anim/animation"//指定补间动画    android:animationOrder="normal"//子元素动画的顺序     android:delay="10"></layoutAnimation><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.junx.viewanimationobjectanimator.Animation.AnimationActivity"    android:layoutAnimation="@anim/layout_animation"    >
<LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.junx.viewanimationobjectanimator.Animation.AnimationActivity"    //指定viewgroup的android:layoutAnimation属性    android:layoutAnimation="@anim/layout_animation"    >

动态使用

    public void layoutAnimation(ListView lv){        Animation animation = AnimationUtils.loadAnimation(this, R.anim.animation);        LayoutAnimationController layoutAnimationController         = new LayoutAnimationController(animation);        layoutAnimationController.setDelay(1f);        layoutAnimationController.setOrder(layoutAnimationController.ORDER_RANDOM);        lv.setLayoutAnimation(layoutAnimationController);    }

View动画的使用场景:Activity的切换效果

    public void test(View view) {        Intent intent = new Intent(this, FrameAnimationActivity.class);        startActivity(intent);        //第一个参数是被打开的页面的进来的动画,第二个参数是当前页面退出的动画效果        //注意该方法必须在startActivity或者finish()后调用才能生肖        overridePendingTransition(android.R.anim.fade_in,android.R.anim.slide_in_left);    }
frament也可以是哟个setCustomAnimations()来设置切换效果

属性动画

View动画致命的缺点是,它只是看起来像一个动画而已,本质上view还是原来那样;属性动画于api11被引入,我们可以通过开源动画库nineoldandroids来兼容以前的版本.nineoldandroids在aip11以前是通过代理view动画来实现,所以在api11以前它本质上还是view动画.属性动画是通过操纵对象的属性来实现的,只要对象有这个属性,就能实现动画效果.默认间隔时间为300ms,帧率为10ms/帧;

ObjectAnimator

动态使用

    //单属性的动画    private void singleAnimator() {        ObjectAnimator backgroundColor = ObjectAnimator.ofInt(btn, "backgroundColor", 0xFFFF8080, 0xFF888888);        backgroundColor.setDuration(3000);        //argb的翻转效果,看起来过渡比较平缓        backgroundColor.setEvaluator(new ArgbEvaluator());        //设置重复次数为无限        backgroundColor.setRepeatCount(ValueAnimator.INFINITE);        //设置重复模式        backgroundColor.setRepeatMode(ValueAnimator.REVERSE);        backgroundColor.start();    }    //属性动画集合    private void setAnimator() {        AnimatorSet animatorSet = new AnimatorSet();        //旋转效果        animatorSet.playTogether                //平移效果                (ObjectAnimator.ofFloat(btn, "rotationX", 0, 360)                , ObjectAnimator.ofFloat(btn, "rotationY", 0, 360)                //缩放效果f                , ObjectAnimator.ofFloat(btn, "scaleX", 1f, 1.5f)                //透明度效果                ,ObjectAnimator.ofFloat(btn, "scaleX", 1f, 1.5f,1f)                ,ObjectAnimator.ofFloat(btn, "scaleY", 1f, 0.5f,1f)                //平移效果                ,ObjectAnimator.ofFloat(btn, "translationX", 1f,300f,0)        );        //支持链式调用        animatorSet.setDuration(3000).start();    }

静态使用

创建animator目录<set xmlns:android="http://schemas.android.com/apk/res/android">    <objectAnimator        android:duration="1000"        android:propertyName="translationX"        android:repeatCount="0"        android:repeatMode="restart"        android:startOffset="15"        android:valueFrom="1"        android:valueTo="100"        android:valueType="floatType" /></set>
    //静态调用属性动画    private void xml() {        AnimatorSet animator = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.object_animator);        animator.setTarget(btn);        animator.start();    }
<Set>对应AnimatorSet    android:ordering:有两个可选值.together,动画集合中的子动画同时播放.sequentially,前后顺序播放.<objectAnimator>对应ObjectAnimator    android:propertyName,表示属性动画作用对象的属性的名称;    android:duration,表示动画的时长    android:valueFrom,表示属性的起始值    android:valueTo    android:startOffset,表示动画开始的延迟时间    android:repeatCount,表示动画的重复次数.默认0,-1表示无限循环    android:repeatMode,表示动画的重复模式    android:valueType,表示属性值的单位或类型,如果是颜色则不需要处理,自动会颜色进行判断<animator>对应ValueAnimator    除了没有propertyName其余属性都和object相同.

属性动画的事件监听

    //属性动画的事件监听    public void setAnimatorListener(Animator animator){        animator.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {            }            @Override            public void onAnimationEnd(Animator animator) {            }            @Override            public void onAnimationCancel(Animator animator) {            }            @Override            public void onAnimationRepeat(Animator animator) {            }        });    }

ValueAnimator

是ObjectAnimator的父类,比objectanimator更为强大,但使用也更复杂;ObjectAnimator生效的要求为:1.object必须提供setXXX(),在没有传递初始值的时候必须额外提供getXXX().2.对属性的改变必须能通过某种途径反应出来,比如使ui改变等等例如,Button有getWidth(确实是获取view的宽度)和setWidth()(但setWidth不是改变view的宽度,就是这么奇葩)方法,但它是由View的子类TextView提供的用于改变tv的最大宽度和最小宽度,并不是我们理解上的视图上的宽度,所以objectanimator无效.解决办法:1.在有条件的情况下,加上getset方法2.使用包装类包装需要改变的view(推荐)3.使用ValueAnimator

静态使用

同objectanimator,在setitem中使用<animator>即可

动态使用

    //值动画    private void valueAnimator() {        ValueAnimator ofInt = ValueAnimator.ofInt(0,100);        ofInt.setDuration(3000);        ofInt.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            //估值器,或许用得上            private IntEvaluator mEvaluator=new IntEvaluator();            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                //获取当前值                Integer animatedValue = (Integer) valueAnimator.getAnimatedValue();                //获取动画进度 0-1f                float animatedFraction = valueAnimator.getAnimatedFraction();                //通过估值器来计算实时的数值第二三个参数为开始值和结束值                Integer evaluate = mEvaluator.evaluate(animatedFraction, 0, 300);                btn_value.getLayoutParams().width=evaluate;                //更新btn的布局大小                btn_value.requestLayout();            }        });        ofInt.start();    }

注意事项

1.注意OOM2.注意内存泄漏,属性动画中无限循环的,需要在页面退出时及时处理.View动画则没有该问题3.兼容性,在3.0以下,兼容性需要小心处理4.View动画而能会导致setVisible()无效,可以调用view.clearAnimation()后setVisible()即可5.不要使用px6.3.0以下的平台,无论是属性动画还是view动画,都是不能点击的 .7.请开启硬件加速
阅读全文
0 0