Android基础-动画

826 阅读4分钟

「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」Android的动画分为三种,分别是帧动画、View动画、属性动画

1.帧动画

帧动画就是预先定义好一组顺序的图片,然后不停的更换前端显示的一张,类似翻书的效果,产生了动画的感觉,共包含两个步骤

  • 在res/drawable目录下定义一个XML文件,根节点为系统提供的animation-list,然后放入指定的图片
  • 使用AnimationDrawable类播放定义好的图片,形成动画效果
//定义动画
<?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/image1" android:duration="200"/>
    <item android:drawable="@drawable/image2" android:duration="200"/>
    <item android:drawable="@drawable/image3" android:duration="200"/>
    <item android:drawable="@drawable/image4" android:duration="200"/>
    <item android:drawable="@drawable/image5" android:duration="200"/>
</animation-list>

//使用动画
ImageView imageView = findViewById(R.id.btnImg);
imageView.setBackgroundResource(R.drawable.frame_animation_list);

AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getBackground();
animationDrawable.start();

2.View动画(补间动画)

设置好一个View的开始和结束状态,中间的状态系统会自动补齐

主要支持4种效果:平移、缩放、旋转、透明

名称标签子类效果
平移动画translateTranslateAnimation移动View
缩放动画scaleScaleAnimation放大或缩小View
旋转动画rotateRotateAnimation旋转View
透明度动画alphaAlphaAnimation改变View的透明度

方式1:

  • xml中声明动画
  • 在Activity中使用AnimationUtils.loadAnimation加载动画Animation,调用View.startAnimation
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromYDelta="0"
        android:toYDelta="0"
        android:fromXDelta="0"
        android:toXDelta="100"
        />
</set>

Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);
animation.setFillAfter(true);
imageView2.startAnimation(animation);

方式2:

使用代码初始化动画

调用View.startAnimation

TranslateAnimation animation = new TranslateAnimation(50, 100, 50, 100);

animation.setFillAfter(true);
imageView2.startAnimation(animation);

需要注意:使用View动画后,View的点击事件触发区域还在动画开始时的位置,需要手动layout布局来处理

使用场景

1.LayoutAnimation

作用于ViewGroup,为ViewGroup指定一个动画,然后,当他的子元素出场时,都具有这种效果,常用于ListView

1.定义LayoutAnimation的xml

2.指定具体的入场动画

3.为ViewGroup指定android:layoutAnimation属性,引入LayoutAnimation的xml

// res/anim/anim_layout.xml
<layoutAnimation
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:delay="0.5"
	android:animationOrder="normal"
	android:animation="@anim/anim_item"/>
// res/anim/anim_item.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
	android:duration="300"
	android:interpolator="@android:anim/accelerate_interpolator"
	android:shareInterpolator="true" >
	<alpha
	android:fromAlpha="0.0"
	android:toAlpha="1.0" />
	<translate
	android:fromXDelta="500"
	android:toXDelta="0" />
</set>
<ListView
	android:id="@+id/list"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:layoutAnimation="@anim/anim_layout"
	android:background="#fff4f7f9"
	android:cacheColorHint="#00000000"
	android:divider="#dddbdb"
	android:dividerHeight="1.0px"
	android:listSelector="@android:color/transparent" />

使用代码实现

ListView listView = (ListView) layout.findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);

2.Activity的切换效果

方法1:

final View frame = findViewById(R.id.frame);

Animation alpha = new AlphaAnimation(1, 0);
alpha.setDuration(MILLISECOND_1500);

alpha.setAnimationListener(new AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) { } // empty

    @Override
    public void onAnimationRepeat(Animation animation) { } // empty

    @Override
    public void onAnimationEnd(Animation animation) {
        frame.setVisibility(View.INVISIBLE);
        startActivity(i);
        finish();
    }
});

frame.startAnimation(alpha);

方法2:

Activity有默认的切换效果,我们可以定制,主要用到overridePendingTransition(int enterAnima, int exiAnima)

Intent intent = new Intent(MainActivity.this, MainActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_from_right, R.anim.exit_to_left);

3.属性动画

  • 属性动画可以定义任何属性的变化
  • 属性动画可以对任何对象执行动画,不限于UI组件。

需要定义的地方:

  • 动画持续时间。默认为 300ms,可以通过 android:duration 属性指定。
  • 动画插值方式。通过 android:interploator 指定。
  • 动画重复次数。通过 android:repeatCount 指定。
  • 重复行为。通过 android:repeatMode 指定。
  • 动画集。在属性资源文件中通过 <set …/> 来组合。
  • 帧刷新率。指定多长时间播放一帧。默认为 10 ms。

属性动画 API

  • Animator: 提供创建属性动画的基类,基本不会直接使用这个类。
  • ValueAnimator:属性动画用到的主要的时间引擎,负责计算各个帧的属性值,基本上其他属性动画都会直接或间接继承它;
  • ObjectAnimator: ValueAnimator 的子类,对指定对象的属性执行动画。
  • AnimatorSet:Animator 的子类,用于组合多个 Animator。

除了这些 API,属性动画还提供了一个 Evaluator ,用来控制属性动画如何计算属性值。

  • IntEvaluator:计算 int 类型属性值的计算器。
  • FloatEvaluator: 用于计算 float 类型属性值的计算器。
  • ArgbEvaluator: 用于计算十六进制形式表示的颜色值的计算器。
  • TypeEvaluator: 可以自定义计算器。

使用 ValueAnimator 创建动画的步骤:

  • 调用 ValueAnimator 的 ofInt()、ofFloat() 或者 ofObject() 静态方法创建 ValueAnimator 实例。
  • 调用 ValueAnimator 的 setXxx() 等方法设置持续时间,插值方式、重复次数等。
  • 调用 ValueAnimator 的 start() 方法启动动画。
  • 为 ValueAnimator 注册 AnimatorUpdateListener 监听器,在该监听器中可以监听 ValueAnimator 计算出来的值改变,并将这些值应用到指定对象上。

使用方式:

  • 使用ValueAnimator或ObjectAnimator的静态工厂方法创建动画
  • 使用资源文件来定义动画

属性动画的使用:

  • 创建 ValueAnimator 或 ObjectAnimator 对象 —— 即可以从 XML 资源文件加载该动画也可以直接调用 ValueAnimator 或者 ObjectAnimator 的静态工厂方法创建动画。
  • 根据需要为 Animator 对象设置属性。
  • 如果需要监听 Animator 的动画开始事件,动画结束事件、动画重复事件、动画值改变事件,并根据事件提供响应处理代码,需要为Animator 对象设置监听器。
  • 如果有多个动画需要同时播放,需要使用 AnimatorSet 组合这些动画。
  • 调用 Animator 对象的 start 启动动画。
ObjectAnimator animator0 = ObjectAnimator.ofFloat(imageView2, "alpha", 1f, 0.5f);
animator0.setDuration(2000);
animator0.start();

//set多个动画
ObjectAnimator animator0 = ObjectAnimator.ofFloat(imageView2, "alpha", 1f, 0.5f);
animator0.setDuration(2000);

ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView2, "scaleX", 0.5f, 1.5f);
animator0.setDuration(2000);

AnimatorSet set = new AnimatorSet();
set.setDuration(4000);
set.playSequentially(animator0, animator1);
set.start();

补充:SVG动画,由于SVG属于矢量图形,优点在于放大后不失真,Android提供了组件来引入SVG图形,有需要的可以自行研究。