您的位置:首页 > 运维架构

动画

2017-05-13 16:58 85 查看
每次绘制View时,ViewGroup中的drawChild函数获取该view的Animation的Transformation值,然后调用canvas.concat(transformToApply.getMatriX()),通过矩阵运算完成帧动画,如果动画没有完成,就继续调用invalidata()函数,启动下次绘制来驱动动画,从而完成整个动画的绘制

安卓动画主要有三类:逐帧动画(Drawable Animation、Frame Animation)、补间动画(View Animaiton、Tweened Animation)、属性动画(Property Animation),其中,View Animation只能修改View组件的部分属性、动画效果是绘制出来的,组件并没有真正改变,而Property Animation可以修改任何对象的任何属性,组件的状态也会跟着改变
Drawable Animation:
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:duration="100">
        <layer-list>
            <item android:drawable="@drawable/login_loading_00" />
            <item android:drawable="@drawable/login_loading_10" />
        </layer-list>
    </item>
    <item android:duration="100">
        <layer-list>
            <item android:drawable="@drawable/login_loading_01" />
            <item android:drawable="@drawable/login_loading_11" />
        </layer-list>
    </item>
</animation-list>
其中,android:oneshot=“true”表示该动画只播放一次,等于false时则循环播放。<item/>标签定义各个帧显示的图片,显示顺序依照<item/>定义顺序,<layer-list/>内包含的图片将层叠起来,在同一帧中一起显示
private AnimationDrawable loadingAnimation;
loadingAnimation.stop();
loadingAnimation.start();
View Animation:
View Animation效果由四个因素决定:1)初始状态;2)结束状态;3)持续时间;4)Interpolator
四大类:AlphaAnimation,RotateAnimation,ScaleAnimation,TranslateAnimation
代码实现View Animation
TranslateAnimation tAnim = new TranslateAnimation(0, 400, 0, 0);
RotateAnimation rAnima = new RotateAnimation(0, 70);
ScaleAnimation sAnima = new ScaleAnimation(0, 5, 0, 5);
AlphaAnimation aAnima = new AlphaAnimation(1.0f, 0.0f);
 
tAnim.setDuration(2000);
tAnim.setInterpolator(new AccelerateDecelerateInterpolator());
translation.startAnimation(tAnim);
XML文件实现View Animation
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <scale
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromXScale="1.0"
        android:toXScale="1.4"
        android:fromYScale="1.0"
        android:toYScale="0.6"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false"
        android:duration="1000" />
    <set
        android:interpolator="@android:anim/accelerate_interpolator"
        android:startOffset="1000">
        <scale …  />
        <rotate
            android:fromDegrees="0"
            android:toDegrees="60"
            android:pivotX="50%"
            android:pivotY="50%"
            android:duration="400" />
    </set>
</set>
android:fillAfter:设置fillAfter为true,动画将保持结束的状态
Animation anim = AnimationUtils.loadAnimation(AnimaXmlActivity.this, R.anim.myanim);
img.startAnimation(anim);
Property Animation:
通过动画的方式改变对象的属性,动画的执行类: ObjectAnimator、ValueAnimator
AnimatorSet用于控制一组动画的执行顺序
AnimatorInflater用于加载属性动画的XML文件
TypeEvaluator类型估值,用于设置动画操作属性的值
PropertyValuesHolder实现一个动画更改多个效果
TimeInterpolator时间插值
ObjectAnimator
ObjectAnimator.ofFloat(view, "rotationX", 0.0F, 360.0F).setDuration(500).start();
1、ObjectAnimator提供了ofInt、ofFloat、ofObject,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束的属性值,当只设置一个属性值的时候,会认为当然对象的属性值为开始(getPropName<
4000
/span>反射获取),设置的值为终点,如果设置两个,则一个为开始、一个为结束。动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新的属性,必须得有getter(设置属性值的时候)和setter方法。
2、如果操作的属性方法内部没有调用view的重绘,比如setRotationX,则需要手动调用
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
       public void onAnimationUpdate(ValueAnimator animation) {
           view.postInvalidate();
           view.invalidate();
        }
});
3.通过ObjectAnimator让View既缩小、又淡出(属性scaleX,scaleY,alpha)
public void rotateAnimRun(final View view) {
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, "zhy", 1.0F,  0.0F).setDuration(500);
    anim.start();
    anim.addUpdateListener(new AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            float cVal = (Float) animation.getAnimatedValue();
            view.setAlpha(cVal);
            view.setScaleX(cVal);
            view.setScaleY(cVal);
        }
    });
}
4.使用propertyValuesHolder实现一个动画更改多个效果:
    public void propertyValuesHolder(View view) {
        PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
        PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
        PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
        ObjectAnimator.ofPropertyValuesHolder
                   (view, pvhX, pvhY,pvhZ).setDuration(1000).start();
    }
ValueAnimator
和ObjectAnimator的区别之处:ValueAnimator本身并没有在属性上做操作,因此,不需要操作对象的属性一定要有getter和setter方法,你可以自己根据当前动画的计算值,来操作任何属性
    public void verticalRun( View view) {
        ValueAnimator animator =
                ValueAnimator.ofFloat(0, mScreenHeight - mBlueBall.getHeight());
        animator.setDuration(1000).start();
        animator.setInterpolator(value)
        animator.addUpdateListener(new AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mBlueBall.setTranslationY((Float) animation.getAnimatedValue());
            }
        });
    }
实现抛物线的效果,水平方向100px/s,垂直方向加速度200px/s*s:
    public void paowuxian(View view) {
        ValueAnimator valueAnimator = new ValueAnimator();
        valueAnimator.setObjectValues(new PointF(0, 0));
        valueAnimator.setDuration(3000);
        valueAnimator.setInterpolator(new LinearInterpolator());
        valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
            // fraction = t / duration
            @Override  
            public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
                PointF point = new PointF();
                point.x = 200 * fraction * 3;
                point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3);
                return point;
            }
        });
        valueAnimator.start();
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {
            @Override  
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF point = (PointF) animation.getAnimatedValue();
                mBlueBall.setX(point.x);
                mBlueBall.setY(point.y);
            }
        });
    }
监听事件:对于动画,一般都是一些辅助效果,比如我要删除个元素,我可能希望是个淡出的效果,但是最终还是要删掉,并不是你透明度没有了,还占着位置,所以我们需要知道动画如何结束
    public void fadeOut(View view) {
        ObjectAnimator anim = ObjectAnimator.ofFloat(mBlueBall, "alpha", 0.5f);
        anim.addListener(new AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) { }
            @Override
            public void onAnimationRepeat(Animator animation) { }
            @Override
            public void onAnimationEnd(Animator animation) { }
            @Override
            public void onAnimationCancel(Animator animation) { }
        });
        anim.start();
    }
AnimatorListenerAdapter:有时候,我只要监听某个状态,这么长的代码我不能接受
anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) { }
});
AnimatorSet
    public void togetherRun(View view) {
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX", 1.0f, 2f);
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY", 1.0f, 2f);
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall, "x",  cx ,  0f);
       ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall, "x", cx);
//anim1,anim2,anim3,anim4接着执行
        AnimatorSet animSet = new AnimatorSet();
        animSet.setDuration(2000);
        animSet.setInterpolator(new LinearInterpolator());
        animSet.playTogether(anim1, anim2);
        animSet.start();
        //anim1,anim2,anim3同时执行,anim4接着执行
        AnimatorSet animSet = new AnimatorSet();
        animSet.play(anim1).with(anim2);
        animSet.play(anim2).with(anim3);
        animSet.play(anim4).after(anim3);
        animSet.setDuration(1000);
        animSet.start();
    }
xml文件实现Property Animation
View Animator 、Drawable Animator在anim文件夹下创建动画。Property Animator在animator文件夹下创建动画
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="together">
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleX"
        android:valueFrom="1.0"
        android:valueTo="0.5">
    </objectAnimator>
    <objectAnimator
        android:duration="1000"
        android:propertyName="scaleY"
        android:valueFrom="1.0"
        android:valueTo="0.5">
    </objectAnimator>
</set>
 
Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);
mMv.setPivotX(0);
mMv.setPivotY(0);
mMv.invalidate();
anim.setTarget(mMv);
anim.start();
orderring表示播放顺序,还有另一个值:sequentially(表示一个接一个执行),缩放、反转等默认是中心缩放,和对称轴为反转线,本例子以左上角为中心点
布局动画(Layout Animations)
LayoutTransition transition = new LayoutTransition();
transition.setAnimator(LayoutTransition.CHANGE_APPEARING,
            transition.getAnimator(LayoutTransition.CHANGE_APPEARING));
transition.setAnimator(LayoutTransition.APPEARING,  null);
transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,  null);
mGridLayout.setLayoutTransition(transition);
过渡动画类型:
LayoutTransition.APPEARING:当View在ViewGroup中出现时,对此View设置动画
LayoutTransition.CHANGE_APPEARING:当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
LayoutTransition.DISAPPEARING:当一个View在ViewGroup中消失时,对此View设置的动画
LayoutTransition.CHANGE_DISAPPEARING:当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画
 
View的anim方法:在SDK11的时候,给View添加了animate方法,更加方便的实现动画效果
public void viewAnim(View view) {
    // need API 12
    mBlueBall.animate().alpha(0).y(mScreenHeight / 2).setDuration(1000)  
    // need API 16
    .withStartAction(new Runnable() {
        public void run() {   Log.e(TAG, "START");  }
    }).withEndAction(new Runnable() {
        @Override
        public void run() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mBlueBall.setY(0);
                    mBlueBall.setAlpha(1.0f);
                }
            });
        }
}).start();
}
 
runOnUiThread:
首先判断是否是UI线程,不是的话就post,如果是的话就正常运行该线程,只要经过主线程中的Handler.post或者postDelayed处理线程runnable则都可以将其转为UI主线程.再说Handler的机制就是来处理线程与UI通讯的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息