欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android动画(一)--视图动画

程序员文章站 2022-03-01 21:05:27
...

Android动画(一)–视图动画

视图动画

View动画一个非常大的缺陷突显,其不具有交互性。当某个元素发生View动画后,
其响应事件的位置依然在动画进行前的地方,所以View动画只能做普通的动画效果,要避免涉及交互操作。

  • 透明度变化(AlphaAnimation)
  • 位移(TranslateAnimation)
  • 缩放(ScaleAnimation)
  • 旋转(RotateAnimation)

这4个动画类都继承自 Animation 类,Animation 类是所有视图动画类的父类,后面讲解的自定义动画 类其实也必须继承 Animation 。

xml 文件中视图动画的目录是res/anim/file_name.xml ,与视图动画不同, xml 文件中属性动画的目录是res/animator/file_name.xml ,属性动画并不推荐在 xml 文件中定义

透明度动画对应标签 ,缩放动画对应标签 ,旋转动画对应标签 ,位移动画对应标签 ,根标签 就表示一个动画集合 AnimationSet

  • alpha
    fromAlpha ---- 透明度起始值,0表示完全透明
    toAlpha ---- 透明度最终值,1表示不透明
  • scale
    fromXScale ---- 水平方向缩放的起始值,比如0
    fromYScale ---- 竖直方向缩放的起始值,比如0
    toXScale ---- 水平方向缩放的结束值,比如2
    toYScale ---- 竖直方向缩放的结束值,比如2
    pivotX ---- 缩放支点的x坐标
    pivotY ---- 缩放支点的y坐标(支点可以理解为缩放的中心点,缩放过程中这点的坐标是不变的;支点默认在中心位置)
  • translate
    fromXDelta ---- x起始值
    toXDelta ---- x结束值
    fromYDelta ---- y起始值
    toYDelta ---- y结束值
  • rotate
    fromDegrees ---- 旋转起始角度
    toDegrees ---- 旋转结束角度

除此之外,还有一些常见的属性值,如下:
android:duration ---- 动画的持续时间
android:fillAfter ---- true表示保持动画结束时的状态,false表示不保持

AnimationUtils.loadAnimation(this, R.anim.ani_view)方法接收两个参数,第一个是当前的上下文环境,第二个就是我们通过 xml 定义的动画

ImageView ivAni = (ImageView) findViewById(R.id.iv_ani);
Animation ani = AnimationUtils.loadAnimation(this, R.anim.ani_view);
ivAni.startAnimation(ani);

代码动态定义

  • AlphaAni
public class AlphaAni extends Activity {

    private LinearLayout llAlpha;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alpha);
        llAlpha = (LinearLayout) findViewById(R.id.ll_alpha);
        beginAnimation();
    }

    // 启动动画
    private void beginAnimation() {
        AlphaAnimation alpha = new AlphaAnimation(0, 1);// 0---->1从透明到不透明
        alpha.setDuration(3000);// 设置动画持续时间
        llAlpha.startAnimation(alpha);// 启动动画
    }
}
  • ScaleAnimation
    接受的四个参数分别是 ScaleAnimation(float fromX, float toX, float fromY, float toY)
  • RotateAnimation
    参数:(0, 360,
    RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f)
  • TranslateAnimation
    参数:(0, 200, 0, 300)

组合动画

把四个View动画装进了一个动画集合(AnimationSet)中

/**
 * AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation四种视图动画的组合动画
 * Created by wondertwo on 2016/3/11.
 */
public class GroupAni extends Activity {

    private LinearLayout llGroup;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group);
        llGroup = (LinearLayout) findViewById(R.id.ll_group);
        beginAnimation();
    }

    // 启动组合动画
    private void beginAnimation() {
        // 创建动画集合
        AnimationSet aniSet = new AnimationSet(false);

        // 透明度动画
        AlphaAnimation alpha = new AlphaAnimation(0, 1);
        alpha.setDuration(4000);
        aniSet.addAnimation(alpha);

        // 旋转动画
        RotateAnimation rotate = new RotateAnimation(0, 360,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(4000);
        aniSet.addAnimation(rotate);

        // 缩放动画
        ScaleAnimation scale = new ScaleAnimation(1.5f, 0.5f, 1.5f, 0.5f);
        scale.setDuration(4000);
        aniSet.addAnimation(scale);

        // 位移动画
        TranslateAnimation translate = new TranslateAnimation(0, 160, 0, 240);
        translate.setDuration(4000);
        aniSet.addAnimation(translate);

        // 动画监听
        aniSet.setAnimationListener(new Animation.AnimationListener() {
            // 动画开始
            @Override
            public void onAnimationStart(Animation animation) {

            }

            // 动画结束,一般在这里实现页面跳转逻辑
            @Override
            public void onAnimationEnd(Animation animation) {
                // 动画结束后,跳转到主页面
                startActivity(new Intent(GroupAni.this, MainActivity.class));
            }

            // 动画重复
            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        // 把动画设置给llGroup
        llGroup.startAnimation(aniSet);
    }
}

AnimatorSet 类提供了一个 play()方法,如果我们向这个方法中传入一个 Animator 对象(ValueAnimator或ObjectAnimator),将会返回一个AnimatorSet.Builder的实例,在play()方法中创建了一个AnimatorSet.Builder类,这个Builder类是AnimatorSet的内部类。

set.play(animator1).with(animator2).after(animator3);

Builder 类采用了建造者模式,每次调用方法时都返回 Builder 自身用于继续构建。
AnimatorSet.Builder中包括以下4个方法。(AnimatorSet正是通过这几种方法来控制动画播放顺序的)

  • after(Animator anim):将现有动画插入到传入的动画之后执行
  • after(long delay):将现有动画延迟指定毫秒后执行
  • before(Animator anim):将现有动画插入到传入的动画之前执行
  • with(Animator anim):将现有动画和传入的动画同时执行

自定义动画

  • 需要继承Animation抽象类,重写initialize()和applyTransformation()方法
    在 initialize() 方法中对一些变量进行初始化,在 applyTransformation() 方法中通过矩阵修改动画数值,从而控制动画的实现过程
  • applyTransformation(float interpolatedTime, Transformation t) 方法在动画的执行过程中会不断地调用,可以看到接收的两个参数分别是 float interpolatedTime 表示当前动画进行的时间与动画总时间(一般在 setDuration() 方法中设置)的比值,从0逐渐增大到1; Transformation t 传递当前动画对象,一般可以通过代码 android.graphics.Matrix matrix = t.getMatrix() 获得 Matrix 矩阵对象,再设置 Matrix 对象,一般要用到 interpolatedTime 参数,以此达到控制动画实现的结果。
  • QQ抖一抖特效:
/**
 * QQ抖一抖特效的自定义View动画实现
 * Created by wondertwo on 2016/3/17.
 */
public class QQTrembleAni extends Animation {
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        t.getMatrix().setTranslate(
                (float) Math.sin(interpolatedTime * 50) * 8,
                (float) Math.sin(interpolatedTime * 50) * 8
                );// 50越大频率越高,8越小振幅越小
        super.applyTransformation(interpolatedTime, t);
    }
}