Android动画

目录

1.帧动画

2.补间动画(视图动画)

平移动画 

 组合动画

3.属性动画


提起动画,会有三种动画类型在Android开发中经常被用到:

  1. 帧动画
  2. 补间动画
  3. 属性动画

1.帧动画

帧动画非常容易理解,其实就是简单的由N张静态图片收集起来,然后我们通过控制依次显示 这些图片,因为人眼"视觉残留"的原因,会让我们造成动画的"错觉",跟放电影的原理一样!

8.4.1 Android动画合集之帧动画 | 菜鸟教程

2.补间动画(视图动画)

也会通常被人称为视图动画,因为作用对象只能是View。

顾名思义,补间动画开发者只需指定动画开始,以及动画结束"关键帧", 而动画变化的"中间帧"则由系统计算并补齐。

补间动画也就是视图动画,是不会改变视图的任何属性的,包括大小,位置等,所以动画一旦结束就会恢复到视图本来的状态

由于无法真正地继承事件交互,所以常被属性动画所取代。但是它仍然有自己的价值。在不涉及到交互,只考虑视觉效果的情况下,它的效率反而比属性动画更高。

补间动画主要分为:

  • 平移动画(Translate)
  • 缩放动画(Scale)
  • 旋转动画(Rotate)
  • 透明度动画(Alpha)

补间动画可以以xml或者java的形式实现,并且只能被用来设置View的动画。

说到补间动画,必须知道Animation抽象类,Animation抽象类是所有补间动画类的基类。下面几个子类和对应的xml写法规定如下:

平移动画 

 以平移动画为例,分别用xml和java实现:

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:toYDelta="0"
     android:toXDelta="200"
     android:duration="500"
     android:fillAfter="true">
 </translate>
 //加载动画
 Animation animation = AnimationUtils.loadAnimation(this, R.anim.animator_translate);
 //执行动画
 testBtn.startAnimation(animation);

 java:

 TranslateAnimation translateAnimation = new TranslateAnimation(0,200,0,0);
 translateAnimation.setDuration(500);//动画执行时间
 translateAnimation.setFillAfter(true);//动画执行完成后保持状态
 //执行动画
 testBtn.startAnimation(translateAnimation);

参数规则如下: 

android:fromXDelta对应的就是TranslateAnimation(float fromXDelta, …) ,起始点X轴坐标,对应数值可以是 数值、百分数、百分数p(相对于view的原位置左上角为原点而言,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)

常用的函数/参数:

android:fillAfter               setFillAfter(boolean)      动画结束时是否保持动画最后的状态

android:fillBefore            setFillBefore(boolean)   动画结束时是否还原到开始前的状态

android:fillEnabled         setFillEnabled(boolean)  与android:fillBefore效果相同

android:interpolator       setInterpolator(Interpolator) 设定插值器(设置动画结束后的效果,譬如回弹等)

 例如:

ScaleAnimation localScaleAnimation = new ScaleAnimation(0.1F, 1.0F, 0.1F, 1.0F, paramView.getWidth() / 2, paramView.getHeight() / 2);
localScaleAnimation.setDuration(1000L);
localScaleAnimation.setInterpolator(new BounceInterpolator());
paramView.startAnimation(localScaleAnimation);

就是设置动画结束后回弹

 组合动画

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

    android:duration="3000"
    android:fillAfter="true"
    android:fillBefore="false"
    android:fillEnabled="false"
    android:interpolator="@android:anim/linear_interpolator"
    android:repeatMode="restart"
    android:startOffset="1000">

    <rotate
        android:duration="3000"
        android:fromDegrees="0"
        android:interpolator="@android:anim/linear_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="infinite"
        android:repeatMode="restart"
        android:startOffset="100"
        android:toDegrees="360" />

    <translate
        android:duration="1000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:startOffset="0"
        android:toXDelta="500"
        android:toYDelta="500" />

    <alpha
        android:duration="5000"
        android:fromAlpha="1"
        android:interpolator="@android:anim/linear_interpolator"
        android:startOffset="2000"
        android:toAlpha="0" />

</set>
public class GroupAnimationActivity extends AppCompatActivity {
    private ImageView mIvImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group_animation);

        mIvImage = findViewById(R.id.iv_image);

        Animation animation = AnimationUtils.loadAnimation(this, R.anim.group);
        mIvImage.startAnimation(animation);

    }
}

java方法:

public class GroupAnimationActivity extends AppCompatActivity {
    private ImageView mIvImage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group_animation);

        mIvImage = findViewById(R.id.iv_image);

        // 组合动画设置
        // 步骤1:创建组合动画对象(设置为true)
        AnimationSet setAnimation = new AnimationSet(true);
        // 步骤2:设置组合动画的属性
        setAnimation.setRepeatMode(Animation.RESTART);
        setAnimation.setStartOffset(1000);
        setAnimation.setDuration(3000);

        // 步骤3:逐个创建子动画(方式同单个动画创建方式,此处不作过多描述)

        // 子动画1:旋转动画
        Animation rotate = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotate.setDuration(3000);
        rotate.setRepeatMode(Animation.RESTART);
        rotate.setRepeatCount(Animation.INFINITE);
        rotate.setStartOffset(100);

        // 子动画2:平移动画
        Animation translate = new TranslateAnimation(0, 500, 0, 500);
        translate.setDuration(1000);
        rotate.setStartOffset(0);


        // 子动画3:透明度动画
        Animation alpha = new AlphaAnimation(1, 0);
        alpha.setDuration(5000);
        alpha.setStartOffset(2000);


        // 步骤4:将创建的子动画添加到组合动画里
        setAnimation.addAnimation(rotate);
        setAnimation.addAnimation(translate);
        setAnimation.addAnimation(alpha);

        // 步骤5:播放动画
        mIvImage.startAnimation(setAnimation);

    }
}

一些问题

1.当同一个view多次调用startAnimation的时候,考虑一下设置的动画时长和两次动画的时间间隔,不然可能会出现上一个动画还没完成,下一个动画就开始了的现象。

2.要调用view.startAnimation 函数而不是 animation.startNow函数来开始动画,后者往往需要用invalidate()函数刷新父控件才能起到开始动画效果,一般没啥必要。

 

请给我上一份动画总结之补间动画_lady_zhou的博客-CSDN博客

3.属性动画

属性动画字如其名,是通过改变 View 的属性值来改变控件的形态,说白了就是通过反射技术来获取控件的一些属性如宽度、高度等的 get 和 set 方法,从而实现所谓的动画效果。所以,这就需要我们的 View (如自定义 View 中)具有 set 和 get 方法,如果没有则会导致程序的 Crash 。

(从代码名字上来看,带Animation的大多是视图动画,而Animator的是属性动画)

Android 属性动画框架 ObjectAnimator、ValueAnimator ,这一篇就够了 - 圆号本昊 - 博客园

设置监听Animator.AnimatorListener

//平移        
ObjectAnimator animator = ObjectAnimator.ofFloat(splashImg, "translationX", -100F);
animator.setDuration(1500L).start();
animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                Intent intent = new Intent(SplashActivity.this, MainActivity.class);
                startActivity(intent);
                finish();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
});

AnimatorListenerAdapter

但是显然我们有些方法用不到,这个时候我们其实可以直接继承AnimatorListenerAdapter而不是去实现Animator.AnimatorListener接口(AnimatorListenerAdapter类为所有的方法提供了一个空实现,所以你可以根据需要实现你需要的,覆盖AnimatorListenerAdapter总原来的方法),如下:

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值