Android动画深入分析-View动画

一、安卓中的动画

1、分类
  • View动画
  • 帧动画
  • 属性动画
2、简单介绍

View动画

概念:
view动画就是通过对场景里的对象不断做图像变换(平移、缩放、旋转、透明度)
,从而产生动画效果。
特点:渐进式动画,支持自定义。

帧动画

概念:
通过顺序播放一系列的图像从而产生动画效果。可以简单的理解为图片切换动画。
缺点:很显然图片过多过大就会导致oom
ps:其实帧动画也是view动画一种,只是他和view动画的表示形式不同。

属性动画

通过动态的改变对象的属性从而达到动画效果。
注意:
安卓api11才有属性动画,在低版本我们无法直接使用属性动画但是我们可以通过兼容库使用它。

二、浅谈View动画

  • view动画的作用对象是安卓中的view控件
  • view动画分为四种(帧动画单独总结)
1、view动画的分类

(1) TranslateAnimation 平移动画
(2) ScaleAnimation 缩放动画(放大或者缩小)
(3) RotateAnimation 旋转动画
(4) AlphaAnimation 透明动画

这四个类是Animation的子类,我们就可以通过这四个类用java代码实现。也可以使用标签(如下)在xml中实现。

四个xml标签

1、translate
2、scale
3、rotate
4、alpha

2、view动画和view之间的关系

我们通过上述的xml标签或者java类写好相应的动画,通过view的startAnimation开启动画即可(这个方法所有view都有参看下源码)

在这里插入图片描述

注意:
这四种动画还可以同时作用在一个view上,通过动画集合作用。
对应java类:AnimationSet
对应xml中的 set标签

3、动画的xml写法

xml写法需要做到:
1、在res目录下建立目录,名字为anim
2、在这个目录上鼠标右键建立 new ->animation resource file
ps:系统默认标签为set, 当然不想使用动画集合时你可以修改为相应的标签即可。

(1)栗子:
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="2000"
    android:fillAfter="true"  
    android:shareInterpolator="true"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator">
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1" />
    <scale
        android:fromXScale="0dp"
        android:fromYScale="0dp"
        android:pivotX="0"
        android:pivotY="0"
        android:toXScale="100dp"
        android:toYScale="100dp" />
    <translate
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="100"
        android:toYDelta="100" />
    <rotate
        android:fromDegrees="0"
        android:pivotX="0"
        android:pivotY="0"
        android:toDegrees="360" />
</set>

java代码中 给view设置view动画

 Animation animation = AnimationUtils.loadAnimation(MainActivity.this, R.anim.test);
 btn.startAnimation(animation);// 给按钮设置view动画

(2)属性讲解

1、interpolator
表示动画集合采用的插值器,插值器影响动画的速度。如上的属性值为加速减速插值器。这个可以不写。系统默认(如上是系统默认的先加速后减速)。如果我们想要动画集合内的动画非匀速。只需要更改插值器的值即可。
2、shareInterpolator
表示集合中的动画是否和集合公用一个插值器,如果集合不指定插值器那么子view需要单独指定插值器,或者使用默认值。
3、duration
动画时常,单位毫秒
4、fillAfter
是否保留动画结束时状态

alpha:表示透明动画,他可以使view的透明度发生变化。取值范围0-1
fromAlpha:
动画开始时的透明度(一般我们设为0,表示完全哪透明)
toAlpha:
动画结束时的透明度(一般设为1,表示完全不透明)

scale:表示缩放动画,可以使view放大或者缩小。
fromXScale:
水平方向缩放的起始值
toXScale:
水平方向缩放的结束值
fromYScale:
竖直放下缩放的起始值
toYScale:
竖直方向缩放的结束值
pivotX、pivotY:
相对某点坐标进行缩放。默认情况下这点是view的中心点。

translate:平移动画,可以使view在水平或者竖直方向上移动。
fromXDelta、toXDelta:水平方向平移的起始结束坐标
fromYDelta、toYDelta:竖直方向平移的起始结束坐标

rotate:旋转动画
fromDegrees、toDegrees:旋转的起始结束度数。
pivotX、pivotY:旋转相对点坐标。

4、代码实现方式

参考:安卓中的补间动画

ps:通过Animation的setOnAnimationListener还可以设置动画监听

5、自定义view动画

除了系统提供的四个view动画类,我们也可以自定义view动画。

实现步骤:

1、创建类继承抽象类Animation
2、实现两个抽象方法:initialize、applyTransformation。
3、在initialize中做初始化操作,在applyTransformation中做相应矩阵变换即可。
ps:有时还需要使用Camera来简化矩阵变换过程。自定义view动画的过程主要是矩阵变化的过程。矩阵变化主要是数学上的概念。一般来说实际开发中很少用到自定义view动画我们就看看安卓apiDemo中的自定义view动画的栗子:

/*
 * Copyright (C) 2007 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.
 */

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();
        // camera.translate,这个方法接受3个参数,分别是x,y,z三个轴的偏移量,我们这里只将z轴进行了偏移,
        if (mReverse) {
            // z的偏移会越来越大。这就会形成这样一个效果,view从近到远
            camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
        } else {
            // z的偏移会越来越小。这就会形成这样一个效果,我们的View从一个很远的地方向我们移过来,越来越近,最终移到了我们的窗口上面~
            camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
        }

        // 是给我们的View加上旋转效果,在移动的过程中,视图还会移Y轴为中心进行旋转。
        camera.rotateY(degrees);
        // 是给我们的View加上旋转效果,在移动的过程中,视图还会移X轴为中心进行旋转。
        // camera.rotateX(degrees);

        // 这个是将我们刚才定义的一系列变换应用到变换矩阵上面,调用完这句之后,我们就可以将camera的位置恢复了,以便下一次再使用。
        camera.getMatrix(matrix);
        // camera位置恢复
        camera.restore();

        // 以View的中心点为旋转中心,如果不加这两句,就是以(0,0)点为旋转中心
        matrix.preTranslate(-centerX, -centerY);
        matrix.postTranslate(centerX, centerY);
    }
}

实现效果:可以沿着y轴旋转,同时沿着z轴平移。

6、帧动画

帧动画是顺序播放一组预先定义好的图片,类似电影播放。系统另外提供一个类来使用帧动画。(如下)

在这里插入图片描述

使用步骤:
(1)drawable建立xml文件,添加图片。
在这里插入图片描述

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/a"
        android:duration="3000" />
    <item
        android:drawable="@drawable/b"
        android:duration="3000" />
    <item
        android:drawable="@drawable/c"
        android:duration="3000" />

</animation-list>

(2)上述drawable 设置view的背景
(3)java代码加载执行(如下)

 final Button btn = findViewById(R.id.btn);
        final AnimationDrawable animationDrawable = (AnimationDrawable) btn.getBackground();

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               animationDrawable.start();
            }
        });

三、View动画的特殊使用场景

view动画除了作用给view之外还有些特殊的场景。
1、比如在viewGroup中可以控制子元素的出场效果。
2、在activity中可以实现不同activity之间的切换特效。

1、ViewGroup和LayoutAnimation

LayoutAnimation就是一个view动画我们可以吧这个动画设置给ViewGroup,这样他的子元素出厂时就具备出场动画效果了。我们常常会看见一些特殊的listview就是设置了LayoutAnimation

首先看看viewGroup的方法
在这里插入图片描述

可以知道安卓中所有的容器也具备此方法。

具体使用:
(1)定义layoutAnimation(res/anim下创建xml文件)
在这里插入图片描述

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

</layoutAnimation>

1、delay代表子元素开始动画的延迟,比如动画的时长1000,则0.5代表每个元素延迟500毫秒后进入。
2、animationOrder代表子元素动画顺序(三种选项)

  • normal 表示顺序显示
  • reverse 表示逆向显示
  • random 表示随机显示

3、animation 加载我们写好的动画

(2)写个入场动画
在这里插入图片描述

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

    <translate
        android:fromXDelta="500"
        android:toXDelta="0" />
    <rotate android:toDegrees="360"
        android:fromDegrees="0"
        android:pivotX="100"
        android:pivotY="100"/>

</set>

(3)吧layoutAnimation文件设置给容器

  • 方式1:直接在容器的xml中添加 android:layoutAnimation="@anim/anim_layout"(如上我们写的layoutAnimation文件)
  • 方式2:代码添加(代码如下)
 LinearLayout linearLayout = findViewById(R.id.ll_layout);
        
        // 动画
        Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_item);
        //传入动画
        LayoutAnimationController controller = new LayoutAnimationController(animation);
        controller.setDelay(0.5f);
        controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
        // 设置给viewGroup
        linearLayout.setLayoutAnimation(controller);

设置后,如果我们的ViewGroup有内容,下次我们打开界面时就会看到子view的动画。

2、Activity的切换效果

Activity有默认的切换效果,但是我们也可以自定义。主要用到activity的overridePendingTransition这个方法。

方法源码:

 * @param enterAnim A resource ID of the animation resource to use for
     * the incoming activity.  Use 0 for no animation.
     * @param exitAnim A resource ID of the animation resource to use for
     * the outgoing activity.  Use 0 for no animation.
     */
    public void overridePendingTransition(int enterAnim, int exitAnim) {
        try {
            ActivityManager.getService().overridePendingTransition(
                    mToken, getPackageName(), enterAnim, exitAnim);
        } catch (RemoteException e) {
        }
    }
  • enterAnim 要打开的activity所需要的动画(被启动activity)
  • exitAnim 要关闭的activity所需要的动画(当前activity)

注意
1、这个方法在startActivity之后使用才生效
2、或者finish内部super.finish之后使用
ps:fragment使用时通过FragmentTransaction中的setCustomAnimation()来添加动画,这个切换动画是view动画。
参考:Github项目解析(九)–>实现Activity跳转动画的五种方式

end

本文来自<安卓开发艺术探索>笔记总结

下篇-属性动画初级用法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值