Android动画总结

Posted AC_Jobim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android动画总结相关的知识,希望对你有一定的参考价值。

Android动画目前分为三种:

  1. Tween Animation 补间动画(又叫view动画),是通过对场景里的对象不断做图像变换(透明度、缩放、平移、旋转)从而产生动画效果,是一种渐进式动画,并且View动画支持自定义。
  2. Frame Animation 帧动画,通过顺序播放一系列图像从而产生动画效果,图片过多时容易造成OOM(Out Of Memory内存用完)异常。
  3. Property Animation 属性动画,这也是在android3.0之后引进的动画,在手机的版本上是android4.0就可以使用这个动画,通过动态的改变对象的属性从而达到动画效果。

补间动画和属性动画的区别:

补间动画只是改变了View的显示效果而已,并不会真正的改变View的属性。而属性动画可以改变View的显示效果和属性。举个例子:例如屏幕左上角有一个Button按钮,使用补间动画将其移动到右下角,此刻你去点击右下角的Button,它是绝对不会响应点击事件的,因此其作用区域依然还在左上角。只不过是补间动画将其绘制在右下角而已,而属性动画则不会。

一、View动画(Tween Animation也称补间动画)

View动画的分类:

单一动画:在这里插入图片描述
复合动画(AnimationSet):由多个单一动画组合在一起的动画

动画相关的操作:

Animation的公用方法:

  • setDuration(long durationMillis) : 设置持续时间(单位ms)
  • setStartOffset(long startOffset) : 设置开始的延迟的时间(单位ms)
  • setFillBefore(boolean fillBefore) : 设置最终是否固定在起始状态
  • setFillAfter(boolean fillAfter) : 设置最终是否固定在最后的状态
  • setAnimationListener(AnimationListener listener) : 设置动画监听

坐标类型:

  • Animation.ABSOLUTE 绝对坐标
  • Animation.RELATIVE_TO_SELF 相对于自己坐标
  • Animation.RELATIVE_TO_PARENT 相对于父容器坐标

动画的启动和结束:

  • 启动动画 : view.startAnimation(animation);
  • 结束动画: view.clearAnimation()

动画监听器 : AnimationListener

  • onAnimationStart(Animation animation) : 动画开始的回调
  • onAnimationEnd(Animation animation) : 动画结束的回调
  • onAnimationRepeat(Animation animation) : 动画重复执行

注意:动画效果有一个很大的问题,就是当移动到指定位置后点击该位置是无效的只能点击原来的位置才有效,它并不是真的移动到该位置了,可以通过属性动画来解决

1.1 ScaleAnimation(缩放动画)

效果展示:
在这里插入图片描述

java代码实现:

在这里插入图片描述

	/*
	 * 1.1  编码实现: 缩放动画 
	 * ScaleAnimation
	 */
	public void startCodeScale(View v) {
		tv_animation_msg.setText("Code缩放动画: 宽度从0.5到1.5, 高度从0.0到1.0, 缩放的圆心为顶部中心点,延迟1s开始,持续2s,最终还原");

		//1. 创建动画对象
		ScaleAnimation animation = new ScaleAnimation(0.5f,0.5f,0.0f,1f,
				Animation.ABSOLUTE,iv_animation.getWidth()/2,Animation.ABSOLUTE,0);
		//或者
		animation = new ScaleAnimation(0.5f, 1.5f, 0, 1,
				Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0);

		//2. 设置
		//延迟1s开始
		animation.setStartOffset(1000);
		//持续2s
		animation.setDuration(2000);
		//最终还原
		animation.setFillBefore(true);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

xml实现:

  • fromXScale/fromYScale:沿着X轴/Y轴缩放的起始比例
  • toXScale/toYScale:沿着X轴/Y轴缩放的结束比例
  • pivotX/pivotY:缩放的中轴点X/Y坐标,即距离自身左边缘的位置,比如50%就是以图像的中心为中轴点。

以 pivotX 为例,其取不同的值的含义:

  • 10:距离动画所在view自身左边缘10像素
  • 10% :距离动画所在view自身左边缘 的距离是整个view宽度的10%
  • 10%p:距离动画所在view父控件左边缘的距离是整个view宽度的10%
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0"
    android:fromYScale="0"
    android:toXScale="1.5"
    android:toYScale="1"
    android:startOffset="1000"
    android:duration="3000"
    android:pivotX="100%"
    android:pivotY="100%"
    android:fillAfter="true">
</scale>
<!-- 宽度从0.0到1.5, 高度从0.0到1.0, 延迟1s开始,持续3s,圆心为右下角, 最终固定 -->
	/*
	 * 1.2 xml实现: 缩放动画 
	 * <scale>
	 */
	public void startXmlScale(View v) {
		tv_animation_msg.setText("Xml缩放动画: Xml缩放动画: 宽度从0.0到1.5, 高度从0.0到1.0, 延迟1s开始,持续3s,圆心为右下角, 最终固定");

		//1. 定义动画文件
		//2. 加载动画文件得到动画对象
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale_test);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

1.2 RotateAnimation(旋转动画)

效果展示:
在这里插入图片描述

java代码实现:

	/*
	 * 2.1 编码实现: 旋转动画 
	 * RotateAnimation
	 */
	public void startCodeRotate(View v) {
		tv_animation_msg.setText("Code旋转动画: 以图片中心点为中心, 从负90度到正90度, 持续5s");
		//1. 创建动画对象
		RotateAnimation animation = new RotateAnimation(-90, 90, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		//2. 设置
		animation.setDuration(5000);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

xml实现:

  • fromDegrees/toDegrees:旋转的起始/结束角度
  • repeatCount:旋转的次数,默认值为0,代表一次,假如是其他值,比如3,则旋转4次 另外,值为-1或者infinite时,表示动画永不停止
  • repeatMode:设置重复模式,默认restart,但只有当repeatCount大于0或者infinite或-1时 才有效。还可以设置成reverse,表示偶数次显示动画时会做方向相反的运动!
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90"
    android:toDegrees="-90"
    android:duration="5000">

</rotate>
<!-- 以左顶点为坐标, 从正90度到负90度, 持续5s -->
	/*
	 * 2.2 xml实现: 旋转动画 
	 * <rotate>
	 */
	public void startXmlRotate(View v) {
		tv_animation_msg.setText("Xml旋转动画: 以左顶点为坐标, 从正90度到负90度, 持续5s");
		//1. 定义动画文件
		//2. 加载动画文件得到动画对象
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_test);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

1.3 AlphaAnimation(透明度渐变动画)

效果展示:
在这里插入图片描述

java代码实现:

	/*
	 * 3.1 编码实现: 透明度动画 
	 * 完全透明 : 0
	 * 完全不透明 : 1
	 * AlphaAnimation
	 */
	public void startCodeAlpha(View v) {
		tv_animation_msg.setText("Code透明度动画: 从完全透明到完全不透明, 持续4s");
		//1. 创建动画对象
		AlphaAnimation animation = new AlphaAnimation(0, 1);
		// 2. 设置
		animation.setDuration(4000);
		// 3. 启动动画
		iv_animation.startAnimation(animation);
	}

xml实现:

  • fromAlpha :起始透明度
  • toAlpha:结束透明度
  • 透明度的范围为:0-1,完全透明-完全不透明
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="1"
    android:toAlpha="0"
    android:duration="4000">

</alpha>
<!-- 从完全不透明到完全透明, 持续4s -->
	/*
	 * 3.2 xml实现: 透明度动画 
	 * <alpha>
	 */
	public void startXmlAlpha(View v) {
		tv_animation_msg.setText("Xml透明度动画: 从完全不透明到完全透明, 持续4s");
		//1. 定义动画文件
		//2. 加载动画文件得到动画对象
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha_test);
//		animation.setFillAfter(true);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

1.4 TranslateAnimation(平移动画)

效果展示:
在这里插入图片描述

java代码实现:

	/*
	 * 4.1 编码实现: 平移动画 
	 * TranslateAnimation
	 */
	public void startCodeTranslate(View v) {
		tv_animation_msg.setText("Code移动动画: 向右移动一个自己的宽度, 向下移动一个自己的高度, 持续2s");

		//1. 创建动画对象
		TranslateAnimation animation = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 1, Animation.ABSOLUTE, 0, Animation.RELATIVE_TO_SELF, 1);
		//2. 设置
		animation.setDuration(2000);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

xml实现:

  • fromXDelta/fromYDelta:动画起始位置的X/Y坐标
  • toXDelta/toYDelta:动画结束位置的X/Y坐标
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%p"
    android:toXDelta="0"
    android:fromYDelta="0"
    android:toYDelta="0"
    android:duration="2000">

</translate>
<!-- 从屏幕的右边逐渐回到原来的位置, 持续2s -->
	/*
	 * 4.2 xml实现: 平移动画 
	 * <translate>
	 */
	public void startXmlTranslate(View v) {
		tv_animation_msg.setText("xml移动动画: 从屏幕的右边逐渐回到原来的位置, 持续2s"); //***此效果用于界面切换的动画效果
		//1. 定义动画文件
		//2. 加载动画文件得到动画对象
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_test);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

1.5 AnimationSet(组合动画)

可以使用AnimationSet把View动画的平移、缩放、旋转、渐变都揉在一起,也是既能通过代码实现,也可以通过xml实现

效果展示:
在这里插入图片描述

java代码实现:

	/*
	 * 5.1 编码实现: 复合动画 
	 * AnimationSet
	 */
	public void startCodeAnimationSet(View v) {
		tv_animation_msg.setText("Code复合动画: 透明度从透明到不透明, 持续2s, 接着进行旋转360度的动画, 持续1s");
		//1. 创建透明动画并设置
		AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
		alphaAnimation.setDuration(2000);
		//2. 创建旋转动画并设置
		RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		rotateAnimation.setDuration(1000);
		rotateAnimation.setStartOffset(2000);//延迟
		//3. 创建复合动画对象
		AnimationSet animationSet = new AnimationSet(true);
		//4. 添加两个动画
		animationSet.addAnimation(alphaAnimation);
		animationSet.addAnimation(rotateAnimation);
		//5. 启动复合动画对象
		iv_animation.startAnimation(animationSet);
	}

xml实现:

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

    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="2000">
    </alpha>
    <rotate
        android:fromDegrees="0"
        android:toDegrees="360"
        android:duration="2000"
        android:startOffset="2000">
    </rotate>

</set>
<!-- 透明度从透明到不透明, 持续2s, 接着进行旋转360度的动画, 持续2s -->
	/*
	 * 5.2  xml实现: 复合动画 
	 * <set>
	 */
	public void startXmlAnimationSet(View v) {
		tv_animation_msg.setText("Xml复合动画: 透明度从透明到不透明, 持续2s, 接着进行旋转360度的动画, 持续2s");
		//1. 定义动画文件
		//2. 加载动画文件得到动画对象
		Animation animation = AnimationUtils.loadAnimation(this, R.anim.set_test);
		//3. 启动动画
		iv_animation.startAnimation(animation);
	}

1.6 Interpolator属性的使用

Interpolator 被用来修饰动画效果,定义动画的变化率,可以使存在的动画效果accelerated(加速),decelerated(减速),repeated(重复)等。

用来控制动画的变化速度,可以理解成动画渲染器,当然我们也可以自己实现Interpolator 接口,自行来控制动画的变化速度,而Android中已经为我们提供了几个个可供选择的实现类:

  • LinearInterpolator:动画以均匀的速度改变
  • AccelerateInterpolator:在动画开始的地方改变速度较慢,然后开始加速
  • AccelerateDecelerateInterpolator:在动画开始、结束的地方改变速度较慢,中间时加速
  • CycleInterpolator:动画循环播放特定次数,变化速度按正弦曲线改变: Math.sin(2 * mCycles * Math.PI * input)
  • DecelerateInterpolator:在动画开始的地方改变速度较快,然后开始减速
  • AnticipateInterpolator:反向,先向相反方向改变一段再加速播放
  • AnticipateOvershootInterpolator:开始的时候向后然后向前甩一定值后返回最后的值
  • BounceInterpolator: 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
  • OvershottInterpolator:回弹,最后超出目的值然后缓慢改变到目的值

而这个东东,我们一般是在写动画xml文件时会用到,属性是:android:interpolator, 而上面对应的值是:@android:anim/linear_interpolator,其实就是驼峰命名法变下划线而已 AccelerateDecelerateInterpolator对应:@android:anim/accelerate_decelerate_interpolator!

例:

//设置线性变化
animation.setInterpolator(new LinearInterpolator());

1.7 动画的监听

在这里插入图片描述

	/*
	 * 6. 测试动画监听
	 */
	public void testAnimationListener(View v) {
		tv_animation_msg.setText("测试动画监听");
		//1. 定义动画文件
		//2. 加载动画文件得到动画对象
		Animation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		animation.setDuration(1000);

		//设置线性变化
		animation.setInterpolator(new LinearInterpolator());
		//设置动画重复次数
		animation.setRepeatCount(3);//重复3次,Animation.INFINITE表示无限次重复
		//设置动画监听
		animation.setAnimationListener(new AnimationListener() {

			@Override
			public void onAnimationStart(Animation animation) {
				Log.e("TAG", "动画开始");
			}

			@Override
			public void onAnimationRepeat(Animation animation) {
				Log.e("TAG", "动画重复");

			}

			@Override
			public void onAnimationEnd(Animation animation) {
				Log.e("TAG", "动画结束");
			}
		});

		//3. 启动动画
		iv_animation.startAnimation(animation);
		
	}

1.8 场景使用

1.8.1 实现登陆失败的抖动效果

效果展示:
在这里插入图片描述

登陆按钮的点击事件:

public void login(View v) {
    //得到输入框的文本
    String name = et_main_name.getText().toString();
    //判断是否是空串, 如果为空串, 显示抖动动画
    if("".equals(name.trim())) {
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.shake);
        et_main_name.startAnimation(animation);
    } else {
        //否则, 提示登陆
        Toast.makeText(this, "去登陆", Toast.LENGTH_SHORT).show();
    }
}

shank.xml:

<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="500"
    android:fromXDelta="0"
    android:interpolator="@anim/cycle_3"
    android:toXDelta="10" />

cycle_3.xml

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

1.8.2 activity的切换动画

显示效果:
在这里插入图片描述
Activity有默认的切换效果,但是我们可以定制,主要用到overridePendingTransition(int enterAnima, int exitAnima)这个方法:

startActivity(new Intent(this, SetupGuide3Activity.class));
overridePendingTransition(R.anim.right_in, R.anim.left_out);

right_in.xml

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

left_out.xml

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

注意, 这个方法必须在startActivity或者finish方法之后调用才会生效

1.8.3 自定义水平进度条

效果展示:
在这里插入图片描述

以上是关于Android动画总结的主要内容,如果未能解决你的问题,请参考以下文章

Android使用片段在viewpager中的页面滚动上放置动画

Android 动画布局和视图

如何在Android中加载带有动画的cardview GridView?

Android TV(leanback)中的持久标头片段(禁用动画)

片段交易动画:滑入滑出

java 将循环显示和不显示过渡动画添加到Android片段