微信扫一扫

028-83195727 , 15928970361
business@forhy.com

Android Tween Animation动画效果详解

android,动画,Animation,补间动画,自定义动画2016-11-08

Android动画分类:

1.补间动画 Tween Animation
2.逐帧动画 Frame Animation

下面我们来讲的就是补间动画:

1.AlphaAnimation 透明动画

代码:

    /**
     * 透明度动画
     *
     * @param view
     */
    private void alphaAnimation(View view) {
        //初始化动画,参数  1.动画开始透明度 2.动画结束透明度
        AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
        //动画持续时间 Animation类的方法,AlphaAnimation继承自Animation类
        alphaAnimation.setDuration(1000);
        //是否停留在最后一帧
        alphaAnimation.setFillAfter(true);
        //设置重复次数
        alphaAnimation.setRepeatCount(3);
        //执行前的等待时间
        alphaAnimation.setStartOffset(100);
        //开启执行动画
        view.startAnimation(alphaAnimation);

        //如果想在动画开始,结束,重复的时候进行一些操作,可以设置动画事件的监听
        alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //动画开始的时候调用
                Log.d("测试", "onAnimationStart");
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //动画结束的时候调用
                Log.d("测试", "onAnimationEnd");
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
                //动画重复执行的时候调用
                Log.d("测试", "onAnimationRepeat");
            }
        });

    }

使用xml文件来配置动画效果:
在res文件夹下新建anim文件夹,这个就是用来放置xml动画文件的文件夹,下面新建test_alpha.xml文件配置文件内容

<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromAlpha="1"
    android:toAlpha="0">
</alpha>

如何调用:

 view.startAnimation(AnimationUtils.loadAnimation(MainActivity.this, R.anim.test_alpha));

效果:

2.RotateAnimation 旋转动画
    /**
     * 旋转动画
     *
     * @param view
     */
    private void rotateAnimation(View view) {
        //初始化参数 1.开始角度 2.结束角度 3.旋转中心点x轴坐标 4.旋转中心点y轴坐标
        RotateAnimation rotateAnimation = new RotateAnimation(0, 360, view.getWidth() / 2, view.getHeight() / 2);
        rotateAnimation.setDuration(1000);
        view.startAnimation(rotateAnimation);
    }

xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360">
    <!--pivotX 旋转中心的x坐标    50%即是相对于其自身宽度的50%
     pivotY 旋转中心的y坐标
     fromDegrees 开始角度
    toDegrees 结束角度  -->

</rotate>

效果:

3.TranslateAnimation 唯一动画
    /**
     * 位移动画
     *
     * @param view
     */
    private void translateAnimation(View view) {
        //参数1.开始x轴位置  2.移动到x轴的位置 3.开始的y轴位置 4.移动到y轴的位置
        TranslateAnimation translateAnimation = new TranslateAnimation(view.getWidth(), view.getWidth(), 0, view.getHeight());
        translateAnimation.setDuration(1000);
        translateAnimation.setFillAfter(true);
        view.startAnimation(translateAnimation);
    }

xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:duration="1000"
    android:toXDelta="100%"
    android:toYDelta="100%">

</translate>

效果:

4.ScaleAnimation 缩放动画
    /**
     * 缩放动画
     *
     * @param view
     */
    private void scaleAnimation(View view) {
        //1.从x轴的缩放比例 2.到x轴的缩放比例 3.从y轴的缩放比例 4.到y轴的缩放比例 5.缩放中心点的x坐标 6.缩放中心点的y坐标
        ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1, view.getWidth() / 2, view.getHeight() / 2);
        scaleAnimation.setDuration(1000);
        view.startAnimation(scaleAnimation);
    }

xml:

<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromXScale="1"
    android:fromYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="2"
    android:toYScale="2">

</scale>

效果:

5.AnimationSet 动画集合
    /**
     * 混合动画
     *
     * @param v
     */
    private void animationSet(View v) {
        //获取屏幕宽度
        WindowManager wm = getWindowManager();
        int width = wm.getDefaultDisplay().getWidth();

        //1.是否共用插值器
        AnimationSet animationSet = new AnimationSet(true);

        //位移
        TranslateAnimation translateAnimation = new TranslateAnimation(0, width / 2 - v.getWidth() / 2, 0, 0);
        translateAnimation.setDuration(0);
        animationSet.addAnimation(translateAnimation);

        //缩放
        ScaleAnimation scaleAnimation = new ScaleAnimation(0, 3, 0, 3, width / 2, v.getHeight() / 2);
        scaleAnimation.setDuration(3000);
        animationSet.addAnimation(scaleAnimation);

        //透明度
        AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
        alphaAnimation.setDuration(3000);
        animationSet.addAnimation(alphaAnimation);

        //旋转
        RotateAnimation rotateAnimation = new RotateAnimation(0, 360, width / 2, v.getHeight() / 2);
        rotateAnimation.setDuration(3000);
        animationSet.addAnimation(rotateAnimation);
        v.startAnimation(animationSet);
    }

xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:shareInterpolator="true">


    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"></alpha>

    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="100%"
        android:toYDelta="100%"></translate>
</set>

AnimationSet就是一个动画集合将所有东西糅合子啊一起执行
效果:

6.关于自定义动画:

在写自定义动画之前,先来看看AlphaAnimation类的源码:

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view.animation;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;

/**
 * An animation that controls the alpha level of an object.
 * Useful for fading things in and out. This animation ends up
 * changing the alpha property of a {@link Transformation}
 *
 */
public class AlphaAnimation extends Animation {
    private float mFromAlpha;
    private float mToAlpha;

    /**
     * Constructor used when an AlphaAnimation is loaded from a resource. 
     * 
     * @param context Application context to use
     * @param attrs Attribute set from which to read values
     */
    public AlphaAnimation(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a =
            context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation);

        mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f);
        mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f);

        a.recycle();
    }

    /**
     * Constructor to use when building an AlphaAnimation from code
     * 
     * @param fromAlpha Starting alpha value for the animation, where 1.0 means
     *        fully opaque and 0.0 means fully transparent.
     * @param toAlpha Ending alpha value for the animation.
     */
    public AlphaAnimation(float fromAlpha, float toAlpha) {
        mFromAlpha = fromAlpha;
        mToAlpha = toAlpha;
    }

    /**
     * Changes the alpha property of the supplied {@link Transformation}
     */
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float alpha = mFromAlpha;
        t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
    }

    @Override
    public boolean willChangeTransformationMatrix() {
        return false;
    }

    @Override
    public boolean willChangeBounds() {
        return false;
    }

    /**
     * @hide
     */
    @Override
    public boolean hasAlpha() {
        return true;
    }
}

发现AlphaAnimation继承自Animation类,所重写的方法有:

1.applyTransformation
这个方法会被父类不断的调用,其中有两个参数
a.float interpolatedTime 这个参数会在动画的执行过程中不断的变化,从开始的时候为0,一直到结束的时候为1
b.Transformation t 这个类中封装了一些属性供子类调用
来看下其具体代码:

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final float alpha = mFromAlpha;
        t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
    }

代码很简单通过t.setAlpha()这个方法去改变控件的alpha属性,然后通过一次次的调用来达到动画的效果

2.willChangeTransformationMatrix
这个方法大概的意思就是该动画是否会改变Matrix矩阵,父类Animaction默认返回true,因为AlphaAnimation只是对透明度的改变不会改变Matrix,所以返回false
3.willChangeBounds
这个方法的意思是动画是否影响指定的视图范围,父类Animaction默认返回true,同理AlphaAnimation返回false
4.hasAlpha
是否有透明度的变化,Animaction默认返回false

AlphaAnimation类除了构造方法之外就这有那么多东西

在来看看RotateAnimation类:

/*
 * Copyright (C) 2006 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.view.animation;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;

/**
 * An animation that controls the rotation of an object. This rotation takes
 * place in the X-Y plane. You can specify the point to use for the center of
 * the rotation, where (0,0) is the top left point. If not specified, (0,0) is
 * the default rotation point.
 * 
 */
public class RotateAnimation extends Animation {
    private float mFromDegrees;
    private float mToDegrees;

    private int mPivotXType = ABSOLUTE;
    private int mPivotYType = ABSOLUTE;
    private float mPivotXValue = 0.0f;
    private float mPivotYValue = 0.0f;

    private float mPivotX;
    private float mPivotY;

    /**
     * Constructor used when a RotateAnimation is loaded from a resource.
     * 
     * @param context Application context to use
     * @param attrs Attribute set from which to read values
     */
    public RotateAnimation(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray a = context.obtainStyledAttributes(attrs,
                com.android.internal.R.styleable.RotateAnimation);

        mFromDegrees = a.getFloat(
                com.android.internal.R.styleable.RotateAnimation_fromDegrees, 0.0f);
        mToDegrees = a.getFloat(com.android.internal.R.styleable.RotateAnimation_toDegrees, 0.0f);

        Description d = Description.parseValue(a.peekValue(
            com.android.internal.R.styleable.RotateAnimation_pivotX));
        mPivotXType = d.type;
        mPivotXValue = d.value;

        d = Description.parseValue(a.peekValue(
            com.android.internal.R.styleable.RotateAnimation_pivotY));
        mPivotYType = d.type;
        mPivotYValue = d.value;

        a.recycle();

        initializePivotPoint();
    }

    /**
     * Constructor to use when building a RotateAnimation from code.
     * Default pivotX/pivotY point is (0,0).
     * 
     * @param fromDegrees Rotation offset to apply at the start of the
     *        animation.
     * 
     * @param toDegrees Rotation offset to apply at the end of the animation.
     */
    public RotateAnimation(float fromDegrees, float toDegrees) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;
        mPivotX = 0.0f;
        mPivotY = 0.0f;
    }

    /**
     * Constructor to use when building a RotateAnimation from code
     * 
     * @param fromDegrees Rotation offset to apply at the start of the
     *        animation.
     * 
     * @param toDegrees Rotation offset to apply at the end of the animation.
     * 
     * @param pivotX The X coordinate of the point about which the object is
     *        being rotated, specified as an absolute number where 0 is the left
     *        edge.
     * @param pivotY The Y coordinate of the point about which the object is
     *        being rotated, specified as an absolute number where 0 is the top
     *        edge.
     */
    public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;

        mPivotXType = ABSOLUTE;
        mPivotYType = ABSOLUTE;
        mPivotXValue = pivotX;
        mPivotYValue = pivotY;
        initializePivotPoint();
    }

    /**
     * Constructor to use when building a RotateAnimation from code
     * 
     * @param fromDegrees Rotation offset to apply at the start of the
     *        animation.
     * 
     * @param toDegrees Rotation offset to apply at the end of the animation.
     * 
     * @param pivotXType Specifies how pivotXValue should be interpreted. One of
     *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
     *        Animation.RELATIVE_TO_PARENT.
     * @param pivotXValue The X coordinate of the point about which the object
     *        is being rotated, specified as an absolute number where 0 is the
     *        left edge. This value can either be an absolute number if
     *        pivotXType is ABSOLUTE, or a percentage (where 1.0 is 100%)
     *        otherwise.
     * @param pivotYType Specifies how pivotYValue should be interpreted. One of
     *        Animation.ABSOLUTE, Animation.RELATIVE_TO_SELF, or
     *        Animation.RELATIVE_TO_PARENT.
     * @param pivotYValue The Y coordinate of the point about which the object
     *        is being rotated, specified as an absolute number where 0 is the
     *        top edge. This value can either be an absolute number if
     *        pivotYType is ABSOLUTE, or a percentage (where 1.0 is 100%)
     *        otherwise.
     */
    public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
            int pivotYType, float pivotYValue) {
        mFromDegrees = fromDegrees;
        mToDegrees = toDegrees;

        mPivotXValue = pivotXValue;
        mPivotXType = pivotXType;
        mPivotYValue = pivotYValue;
        mPivotYType = pivotYType;
        initializePivotPoint();
    }

    /**
     * Called at the end of constructor methods to initialize, if possible, values for
     * the pivot point. This is only possible for ABSOLUTE pivot values.
     */
    private void initializePivotPoint() {
        if (mPivotXType == ABSOLUTE) {
            mPivotX = mPivotXValue;
        }
        if (mPivotYType == ABSOLUTE) {
            mPivotY = mPivotYValue;
        }
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        float degrees = mFromDegrees + ((mToDegrees - mFromDegrees) * interpolatedTime);
        float scale = getScaleFactor();

        if (mPivotX == 0.0f && mPivotY == 0.0f) {
            t.getMatrix().setRotate(degrees);
        } else {
            t.getMatrix().setRotate(degrees, mPivotX * scale, mPivotY * scale);
        }
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
        mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
    }
}

一看到除了构造方法外重写的父类的方法又多了一个initialize();只看方法名也看的出来这是一个初始化的方法,在动画开始之前会调用这个方法,其中传递过来的参数分别是,动画目标对象的宽高以及其父对象的宽高,然后在applyTransformation中通过t.getMatrix()获取到矩阵,去执行旋转的方法。

至于其他的ScaleAnimation和TranslateAnimation也都是重写了initialize()和applyTransformation()通过Matrix矩阵来不断的修改属性来达到动画的效果

只要明白了这个,那么再来写自定义动画就简单多了
下面我们来写一个拉伸的动画效果:
代码:

package wkk.app12;

import android.view.animation.Animation;
import android.view.animation.Transformation;

/**
 * Created by wkk on 2016/11/8.
 */
public class Animation_m extends Animation {

    private int height;

    //动画执行之前调用此方法,分别是目标对象以及其父容器的宽高
    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        this.height = height;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        //1.补间 从0至1     本方法将会在动画执行期间不断调用
        //x轴 y轴   中心点x轴 y轴
        t.getMatrix().setSkew((float) Math.sin(interpolatedTime * 6), 0, 0, height);
    }
}

效果:

ps:
起个什么什么详解的名字感觉自己也变成了大神一样,哈哈哈…