Android开发Android技术知识Android开发

Android进阶(7)| 动画

2019-05-01  本文已影响5人  yzbkaka
本节目录

一.View动画

1.View动画的种类

Android中的View动画分为平移动画、缩放动画、旋转动画、透明度动画和帧动画。其中帧动画的表现形式和前四种的变换效果不太一样,所以在后面会单独来介绍,这里先来介绍前4种。

2.View动画详解

动画的子类:View动画的前四种变换效果对应着Animation的四个子类:TranslateAnimation、ScaleAnimation、RotateAnimation和AlphaAnimation。

创建的方法:前4种动画既可以通过XML定义,创建的位置是res/anim/filename,也可以通过代码来进行动态的创建,不过对于View动画来说,还是建议采用XML来进行定义动画。要使用View动画,首先要创建出动画的XML文件,下面给出每一个标签里面的具体属性:

实际操作的例子:首先我们要新建一个xml文件,如下所示:

// res/anim/animation_test.xml
...
<set xmlns:android="http://..."
    android:fillAfter="true"
    android:zAdjustment="normal">

<translate
    android:duration="100"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="100"
    android:toYDelta="100"
    android:interpolator="@android:anim/linear_interpolator"/>

<rotate
    android:duration="400"
    android:fromDegrees="0"
    android:toDegrees="90"/>

</set>

我们在定义了一个平移和缩放的动画集合,接着我们将这个动画设置到一个按钮上:

Button mButton = (Button)findViewById(R.id.button1);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.animation_test);  //给出具体的动画位置
mButton.startAnimation(animation);  //启动动画

3.帧动画

概念:帧动画是按顺序播放一组预先定义好的图片,类似与电影播放。之所以说它与前四种View动画不同,是因为系统为它单独提供了另一个类AnimationDrawable。

创建方法:帧动画是需要使用XML来进行定义一个AnimationDrawable,实例如下:

// res/drawable/frame_animation.xml
... 
<animation-list xmlns:android="http://..."
    android:onshot="false">
    <item android:drawable="图片1"/>
    <item android:drawable="图片2"/>
    <item android:drawable="图片3"/>
/>

如果要将上述的Drawable设置到View上,则需要进行如下操作:

Button mButton = (Button)findViewById(R.id.button1);
mButton.setBackgroundResource(R.drawable.frame_animation);  //先将Drawable设置为背景
AnimationDrawable drawable = (AnimationDrawable) mButton.getBackground();
drawable.start();

二.View动画的特殊使用场景

1.LayoutAnimation

概念:LayoutAnimation作用于ViewGroup,为ViewGroup指定一个动画,这样当它的子元素出场时都会有这种效果。这种效果常常被用在ListView上,即它每一个item都会以一定的动画形式出现。

使用方法:首先还是需要在XML中定义:

// res/anim/anim_layout.xml
<LayoutAnimation xmlns:android="http://..."
    android:delay="0.5"
    android:animationOrder="normal"
    android:animation="@anim/anim_item"
/>

它的各个属性的介绍如下:

在XML中定义好了之后,就需要为子元素设置具体的入场动画:

// res/anim/anim_item.xml
<set xmlns:android="http://..."
    android:duration="300"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:sharedInterpolator="true">

    <alpha
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />

    <translate
        android:fromXDelta="500"
        android:toXDelta="0" />
</set>

最后在ViewGroup中指定android:LayoutAnimation属性即可:

<ListView
    ...
    android:LayoutAnimation="@anim/anim_layout.xml"
    ...
/>

2.Activity的切换效果

使用方法:Activity的切换我们也可以使用自定义的效果,这里时主要用到overridePending Transition(int enterAnim,int exitAnim)这个方法,其中enterAnim表示的是Activity被打开时的动画资源id,exitAnim时Activity被暂停时的动画资源id。具体的使用方法如下:

Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);

public void finish(){
    super.finish();
    overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
}

注意:overridePending Transition(int enterAnim,int exitAnim)方法必须要在startActivity()或者是finish()之后被调用才能生效。

三.属性动画

属性动画时API11新加入的特性,和View动画所不同的是,它对作用对象进行了拓展,属性动画可以对任何对象(甚至不是对象的)做动画,并且不再拘泥于View动画的5种模式。

1.使用属性动画

实现原理:属性动画是在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。在属性动画中几个比较常用的动画类是:ValueAnimator、ObjectAnimator和AnimmatorSet,其中ObjectAnimator继承自ValueAnimator,而AnimmatorSet则表示一个动画的集合。

操作方法:举例来说:
(1)让一个对象沿着y轴向上平移一段距离:

ObjectAnimator.ofFloat(myObject,"translationY",-myObject.getHeight()).start();

(2)改变一个对象的背景色属性:

ValueAnimator colorAnim = ObjectAnimator.ofInt(this,"backgroundColor",0xfff8080,0xff8080ff);  //实现从0xfff8080到0xff8080ff的颜色渐变
colorAnim.setDuration(3000);  //设置时间
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);  //设置循环的次数
colorAnim.setRepeatMode(ValueAnimator.REVERSE);  //动画的模式
colorAnim.start();

除了可以使用代码来动态的创建动画外,也可以使用XML来静态的创建动画,属性动画需要定义再res/amimator目录下,其中<set>标签对应着AnimatorSet,<animator>对应着valueAnimator,而<objectAnimator>则对应着ObjectAnimator。举例来说:

// res/animator/animator.xml

<set android:ordering="together"  设置动画组的播放顺序,这里是顺序播放

    <objectAnimator
        android:propertyName="x"  改变属性的名称
        android:duration="300"  持续时间
        android:valueTo="200"  属性改变之后的值
        android:valueType="intType"/>  指定属性类型为整型

    <objectAnimator
        android:propertyName="y"
        android:duration="300"
        android:valueTo="300"
        android:valueType="intType"/>
</set>


AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,R.anim.animator);  //设置动画
set.setTarget(mButton);  //设置控件
set.start();

2.插值器和估值器

插值器的概念:即TimeInterpolator,它的作用是根据时间流逝的百分比来计算出当前属性值改变的百分比。系统预置的插值器有:LinearInterpolator(匀速)、AcclerateDecelerateInterpolat-or(两头慢中间快)和DecelerateInterpolator(越来越慢)。

估值器的概念:即TypeEvaluator,它的作用是根据当前属性改变的百分比来计算改变后的属性。系统预置的估值器有IntEvaluator(整型)、FloatEvaluator(浮点型)和ArgeEvaluator(Color属性)。

工作过程:

4.属性动画的监听器

监听器的种类:属性动画的监听器主要用于监听动画的播放过程,主要是有如下的两个接口:AnimatorUpdateListener和AnimatorListener。

监听器的定义:
(1)AnimationListener

public static interface AnimatorListener{
    void onAnimationStart(Animator animation);  //动画开始
    void onAnimationEnd(Animator animation);  //动画结束
    void onAnimationCancel(Animator animation);  //动画取消
    void onAnimationRepeat(Animator animation);  //动画重复
}

(2)AnimatorUpdateListener

public static interface AnimatorUpdateListener{
    void onAnimationUpdate(ValueAnimator animation);  //当动画的某一帧出现改变时就会被调用
}

5.对任意属性做动画

属性动画的原理:属性动画的要求时被动画作用的对象能够提供该属性的get和set方法,属性动画就根据外界传递的该属性的初始值和最终值,以动画的效果多次去调用set方法,直到所传递的值达到于最终值。

实现属性动画的条件:基于上述的原理,我们时能够对某一对象(object)的任意属性(abc)设置属性动画的,不过如果想让动画生效,还是需要同时满足以下两个条件的:
1)object必须提供setAbc()方法,如果动画的时候没有提供初始值,则还需要提供getAbc()方法来获取到该属性的初始值。
2)object的setAbc()对属性abc所做的改变必须能够通过某种形式反映出来,否则动画无效。

对于无法满足条件的对象解决方案:从上面可以看出我们如果要对某一对象实现属性动画,就必须要满足它所要求的两个条件,但是在很多情况下我们的对象是无法满足这些条件的,针对这些情况,Android官方提供了3种解决方法:

public void performAnimate(){
    ViewWrapper wrapper = new ViewWrapper(mButton);
    ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
}

@Override
public void onClick(View view){
    if(v == mButton){
        performAnimate();
    }
}


private static class ViewWrapper{  //用类来封装get和set方法
    private View mTarget;

    public ViewWrapper(View target){
        mTarget = target;
    }

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

    public void setWidth(int width){
        mTarget.getLayoutParams().width = width;
        mTarget.requestLayout();
    }
}
private void performAnimate(final View target,final int start,final int end){
    ValueAnimator valueAnimator = new ValueAnimator.ofInt(1,100);  //设置时间
    ValueAnimator.addUpdateListener(new AnimatorUpdateListener(){
        private IntEvaluator mEvaluator = new IntEvaluator(); //设置一个估值器

        @Override
        public void onAnimationUpdate(ValueAnimator animation){
            int currentValue = (Integer) animator.getAnimatedValue();  //获得当前动画的进度

            float fraction = animator.getAnimatedFraction();  //获得当前进度占整个动画的过程的比例
            target.getLayoutParams.width() = mEvaluator.evaluate(fraction,start,end);  //使用估值器进行计算
            target.requestLayout();

        }
    });

    valueAnimator.setDuration(5000).start();
}


@Override
public void onClick(View v){
    if(v == mButton){
        performAnimate(mButton,mButton.getWidth(),500);
    }
}

四.使用动画的注意事项

上一篇下一篇

猜你喜欢

热点阅读