当前位置:   article > 正文

Android开发——View动画、帧动画和属性动画详解_android 属性动画会改变left top吗

android 属性动画会改变left top吗

0. 前言  

Android动画是面试的时候经常被问到的话题。我们都知道Android动画分为三类:View动画、帧动画和属性动画

先对这三种动画做一个概述:

View动画是一种渐进式动画,定义动画开始和结束的两帧,并指定动画变化的时间和方式。并通过平移、缩放、旋转和透明度四种效果结合成复杂的动画效果。而在开始和结束帧之间插入的渐变值依据的是插值器。

帧动画是通过不停的切换图片实现动画效果。

属性动画是不停的改变对象的属性来实现动画效果。4.4新出的过渡动画只是对属性动画的一层封装。

本文原创,转载请注明出处:Android开发——View动画、帧动画和属性动画详解_SEU_Calvin的博客-CSDN博客

1.  View动画  

1.1  系统提供的四种View动画(补间动画)

View动画可以在res/anim/name.xml文件里进行配置,四种View动画的渐变式变换分别对应<translate><scale><rotate><alpha>四个标签,动画集合可以使用<set>标签。xml的各个动画属性比较简单,这里就不再贴实例代码了。只需要注意如何应用配置好的xml文件来启动动画即可:

view.startAnimation(AnimationUtils.loadAnimation(this,R.anim.myanimation));

这些当然也可以在Java代码里进行配置,也比较简单,这里写了一个示例代码:

  1. splash = (RelativeLayout)findViewById(R.id.splash);
  2. //旋转动画
  3. RotateAnimation rotateAnimation = new RotateAnimation(0,360,
  4. Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
  5. rotateAnimation.setDuration(2000);
  6. rotateAnimation.setFillAfter(true);
  7. //缩放动画
  8. ScaleAnimation scaleAnimation = new ScaleAnimation(0,1,0,1,
  9. Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
  10. scaleAnimation.setDuration(2000);
  11. scaleAnimation.setFillAfter(true);
  12. //渐变动画
  13. AlphaAnimation alphaAnimation = new AlphaAnimation(0.2f,1.0f);
  14. alphaAnimation.setDuration(2000);
  15. alphaAnimation.setFillAfter(true);
  16. //平移动画
  17. TranslateAnimation translateAnimation = newTranslateAnimation (0,0,100,100);
  18. translateAnimation.setDuration(2000);
  19. translateAnimation.setFillAfter(true);
  20. //动画集合
  21. AnimationSet animationSet = new AnimationSet(true);
  22. animationSet.addAnimation(rotateAnimation);
  23. animationSet.addAnimation(scaleAnimation);
  24. animationSet.addAnimation(alphaAnimation);
  25. animationSet.addAnimation(translateAnimation);
  26. //启动动画
  27. plash.startAnimation(animationSet);

1.2   自定义View动画

实际项目中,如果四种基本动画无法满足需求,就需要自定义补间动画了

完成自定义动画需要继承Animation类,并重写其initialize()以及applyTransformation()前者用于一些初始化的操作,后者用于进行矩阵变换

1.3     ViewGroup的所有子元素设置动画

上面1.11.2都是给View设置动画效果,Android同样提供了为ViewGroup设置android:layoutAnimation=”@anim/layout_anim”来达到ViewGroup中所有子元素设置动画的目的。下面给出相关代码:

  1. //res/anim/anim/layout_anim.xml
  2. <layoutAnimation xmlns:android=” http://schemas.android.com/apk/res/android”
  3. android:delay=”0.1//动画延迟时间为0.1*T,本例为100ms
  4. android:animationOrder=”normal” //子元素的播放动画顺序为顺序,也有reverse以及random
  5. android: animation=” @anim/layout_anim_item”/>
  6. //res/anim/anim/layout_anim_item.xml
  7. <?xml version=”1.0” encoding=”utf-8”?>
  8. <set xmlns:android=”http://schemas.android.com/apk/res/android”
  9. animation:duration=”200//每个子元素的动画周期T
  10. animation:interpolator=”@android:anim/accelerate_ interpolator” //指定插值器
  11. animation:shareInterpolator=”true”> //表示所有子元素共享该插值器
  12. <alpha android:fromAlpha=”0.2” android: toAlpha =”1.0”/>
  13. <translate android:fromXDelta=”100” android: toXDelta =”0”/>
  14. </set>

1.4     Activity切换设置动画

估计大家也都用过,在startActivity()之后使用,使Activity切换时达到一个平移的动画效果

overridePendingTransition(R.anim.tran_in,R.anim.tran_out);
  1. //res/anim/tran_in
  2. <?xml version="1.0" encoding="utf-8"?>
  3. <translate xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:duration="500"
  5. //表示从屏幕100%的位置开始,因此tran_out当然是toXDelta="-100%p",其他不变
  6. android:fromXDelta="100%p"
  7. android:fromYDelta="0"
  8. android:toXDelta="0"
  9. android:toYDelta="0" >
  10. </translate>

2.   帧动画

上面也提到了,帧动画就是不停的切换图片实现动画效果。很明显容易OOM,所以使用帧动画要注意图片大小。

帧动画的使用也很简单,使用示例如下:

  1. //res/drawable/myanimation.xml
  2. <?xml version=”1.0” encoding=”utf-8”?>
  3. <animation-list xmlns:android=”http://schemas.android.com/apk/res/android”
  4. animation:oneshot=”false” > //false为循环播放,true为类似于View动画的setFillAfter效果
  5. <item android: drawable =”@ drawable/ drawable 1” android:duration=” 200”>
  6. <item android: drawable =”@ drawable/ drawable 2” android:duration=” 200”>
  7. </animation-list>
  8. //在代码里加载动画设置并启动动画
  9. view.setBackgroundResource(R.drawable.myanimation.xml);
  10. (AnimationDrawable)view.getBackground.start();

3.   属性动画

View动画的那四种效果有很明显的缺点,绘制出来的效果其实并没有真正改变View的属性,即lefttoprightbottom的值,只是系统临时绘制的结果。这样View点击位置并没有发生变化。针对这个问题,从Android3.0开始属性动画应运而生。

属性动画本质是通过改变新增的属性(如平移translationX/Y、缩放scaleX/Y、旋转rotationX/Y等)并刷新屏幕来实现动画效果,并且实现点击位置的实时改变。但是属性动画仍然不会修改原始的上下左右四个值。最后需要注意的是,属性动画不止用于View,还可以用于任何对象

下面介绍与属性动画相关的类和方法:

 

3.1  setTranslationX方法

该方法直接更改view属性的方法,因为有时候不需要使用动画效果。

  1. view.setTranslationX(x);//3.0以后
  2. ViewHelper.setTranslationX(view,x);//3.0以前通过NineOldAndroid库实现

3.2   ValueAnimator

ValueAnimator只定义和执行动画流程,并没有直接操作属性值的逻辑,需要添加动画更新的监听,并在onAnimationUpdate()中执行自定义的动画逻辑。

  1. ValueAnimator animator = ValueAnimator.ofInt(1, 100); //定义动画,相当于1秒内数100个数
  2. animator.addUpdateListener(new AnimatorUpdateListener() {
  3. @Override
  4. public void onAnimationUpdate(ValueAnimator animation){
  5. float fraction = animation.getAnimatedFraction();//动画进度值0-1
  6. //整型估值器帮我们计算了start+(end-strat)*fraction,并设置给控件的宽度
  7. view.getLayoutParams().width = new IntEvaluator().evaluate(fraction,start,end) //不需要set方法
  8. view.requestLayout();
  9. }
  10. });
  11. animator.setDuration(1000).start();

3.3    ObjectAnimator

ObjectAnimator继承自ValueAnimator,它允许直接改变view的属性,下面通过一个例子介绍。

  1. //x轴方向缩放的例子
  2. ObjectAnimator animator = ObjectAnimator.ofFloat(view,”scaleX”,2.0f);
  3. animator.setDuration(1000);
  4. animator.setStartDelay(1000);
  5. animator.start();

大多数的情况使用ObjectAnimator就足够了,因为它不用像ValueAnimator那样自己写动画更新的逻辑,但是ObjectAnimator有一定的限制——它需要目标属性提供指定的处理方法(譬如提供get/set方法),这是因为ObjectAnimator的原理是不停的调用set方法更新属性值,并且如果我们没有传递初始值,系统会直接调用get方法获取值。而上面3.2中介绍过的ValueAnimator则不直接操作属性值,所以要操作对象的属性可以不需要se/get方法,你完全可以通过当前动画的计算去修改任何属性。

针对这个问题,官方推荐我们用一个类包装原始对象,间接为其提供get/set方法,实现起来很简单,实例如下:

  1. ViewWrapper wrapper = new ViewWrapper(view);
  2. ObjectAnimator.ofInt(wrapper,”width”,200).setDuration(1000).start();
  3. private static class ViewWrapper{
  4. private View myView;
  5. public ViewWrapper(View view){
  6. myView = view;
  7. }
  8. public int getWidth(){
  9. return myView.getLayoutParams().width;
  10. }
  11. public int setWidth(int width){
  12. myView.getLayoutParams().width = width;
  13. myView.requestLayout();
  14. }
  15. }

3.4  ViewPropertyAnimation

ViewPropertyAnimationNineOldAndroid中的类,简化了ObjectAnimator类的操作,并且NineOldAndroid库兼容了3.0以前的Android版本。下面经过一个例子介绍。

  1. //x轴方向缩放的例子,效果同3.3
  2. ViewPropertyAnimation.animate(view).scaleX(2.0f).setDuration(1000)
  3. .setInterpolator(new OvershootInterpolator())
  4. .setStartDelay(1000).start();

3.5  AnimationSet

动画集合,提供把多个动画组合成一个组合的机制,并可设置动画的时序关系,如同时播放、顺序播放或延迟播放。具体使用方法比较简单,如下所示:

  1. ObjectAnimator objectAnimator1= ObjectAnimator.ofFloat(view, "alpha", 1.0f, 0f);
  2. ObjectAnimator objectAnimator2= ObjectAnimator.ofFloat(view, "translationY", 0f, 30f);
  3. ObjectAnimator objectAnimator3= ObjectAnimator.ofFloat(view, "translationX", 0f, 30f);
  4. AnimatorSet animatorSet = new AnimatorSet();
  5. animatorSet.setDuration(5000);
  6. animatorSet.setInterpolator(new LinearInterpolator());
  7. // animatorSet.playTogether(objectAnimator1, objectAnimator2. objectAnimator3); //三个动画同时执行
  8. // 12同时执行,3接着执行
  9. animatorSet.play(objectAnimator1).with(objectAnimator2);
  10. animatorSet.play(objectAnimator3).after(objectAnimator2);
  11. animatorSet.start();

4.  插值器总结

4.1  系统已经提供给我们的插值器

各种插值器都是实现了Interpolator接口,下面来看一下系统已经提供给我们直接使用的插值器。

 

4.2  自定义插值器

Interpolator都实现了Interpolator接口,而Interpolator接口又继承自TimeInterpolatorTimeInterpolator接口定义了一个由系统调用的getInterpolation(float input)方法,其中参数input代表动画完成进度,在01之间。我们自定义插值器只需要实现Interpolator接口并覆写getInterpolation()方法即可实现自定义的动画效果。

 

如下就是一个动画始末速率较慢、中间加速的AccelerateDecelerateInterpolator插值器:

  1. public class AccelerateDecelerateInterpolator extends BaseInterpolator
  2. implements NativeInterpolatorFactory {
  3. ......
  4. public float getInterpolation(float input) {
  5. return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
  6. }
  7. ......
  8. }

5.  动画监听器

我们在平时开发过程中,经常要监听动画完成的时机以继续业务逻辑,那么我们可以通过给动画集合设置AnimationListener监听器来实现。分别可以监听动画开始、结束、取消以及重复播放

  1. //监听动画完成
  2. animationSet.setAnimationListener(new Animation.AnimationListener() {
  3. @Override
  4. public void onAnimationStart(Animation animation) {}
  5. @Override
  6. public void onAnimationEnd(Animation animation) {}
  7. @Override
  8. public void onAnimationRepeat(Animation animation) {}
  9. @Override
  10. public void onAnimationCancel(Animation animation) {}
  11. });

最后若想监听动画中每一帧的回调,我们可以设置AnimatorUpdateListener监听器并重写其onAnimationUpdate()方法即可。

至此关于Android动画的知识总结完毕。

转载请注明出处:Android开发——View动画、帧动画和属性动画详解_SEU_Calvin的博客-CSDN博客


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/319899
推荐阅读
相关标签
  

闽ICP备14008679号