android 艺术开发探索之动画(animation)
2016-08-17 15:37
405 查看
名称 | 类型 | 子类 | 标签 | 效果 |
---|---|---|---|---|
平移动画 | view动画 | TranslateAnimation | < translate > | 移动view |
缩放动画 | view动画 | ScaleAnimation | < scale > | 放大或缩小view |
旋转动画 | view动画 | RotateAnimation | < RotateAnimation> | 旋转view |
透明度动画 | view动画 | AlphaAnimation | < AlphaAnimation> | 改变view的透明度 |
帧动画 | view动画 | AnimationDrawable | < animation-list > | 顺序播放一组预先定义好的的图片 |
layoutAnimation动画 | view动画 | AnimationDrawable | < layoutAnimation> | 作用于viewgroup,子元素出厂时都具有此效果 |
属性动画 | 属性动画 |
<?xml version="1.0" encoding="utf-8"?> <!-- set对应得是动画集合,对应类是AnimationSet,--> <set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1" android:fillAfter="true" android:shareInterpolator="true"> <!-- 表示集合中的动画是否和集合共享一个插值器,duration是指持续时间,fillAfter动画结束后view是否停留在结束位置--> <!-- 表示透明度动画--> <alpha android:fromAlpha="1" android:toAlpha="0"></alpha> <!-- 表示缩放动画,默认缩放轴点为view中心,左右方向同时缩放,若设右边界,view只会向左边进行缩放--> <scale android:fromXScale="1" android:toXScale="0" android:fromYScale="1" android:toYScale="0" android:pivotY="1" android:pivotX="1" > </scale> <!-- 表示在水平和垂直方法平移动画--> <translate android:fromXDelta="1" android:fromYDelta="1" android:toXDelta="0" android:toYDelta="0"> </translate> <!-- 表示旋转动画,默认view的中心为旋转轴--> <rotate android:fromDegrees="10" android:pivotX="1" android:pivotY="1" android:toDegrees="30"> </rotate> </set>
加载动画
Animation animation= AnimationUtils.loadAnimation(this,R.anim.demo); m.startAnimation(animation);
帧动画xml,帧动画的xml要写的drawable下面,animation-list才能识别
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="true" > <item android:drawable="@drawable/icon1" android:duration="150"></item> <item android:drawable="@drawable/icon2" android:duration="150"></item> <item android:drawable="@drawable/icon3" android:duration="150"></item> <item android:drawable="@drawable/icon4" android:duration="150"></item> <item android:drawable="@drawable/icon5" android:duration="150"></item> <item android:drawable="@drawable/icon6" android:duration="150"></item> </animation-list>
m.setBackgroundResource(R.drawable.demo1); AnimationDrawable drawable=(AnimationDrawable)m.getBackground(); drawable.start();
LayoutAnimation作用于Viewgroup,当其子元素出场时也具有这种效果,一般用于listview这种带列表的控件。
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay="0.5" android:animationOrder="normal" android:animation="@anim/demo1"> <!--假如demo1动画周期为1000ms,那么0.5表示每个item出场都需延时500ms, 第一个是500ms,第二个就是1000ms,animationOrder为子元素的动画顺序,比如随机出场和逆向出场, 对于listview,只需给其加上android:layoutAnimation这个属性就好--> </layoutAnimation>
Activity的切换效果主要方法:
//此方法只能在startactivity和finish()之后被调用才有效。 overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim);
Fragment切换效果主要方法:
//这里动画必须是View动画 FragmentTransaction transaction= getChildFragmentManager().beginTransaction(); transaction.setCustomAnimations(R.anim.enter_anim,R.anim.exit_anim);
属性动画ObjectAnimator , ValueAnimator, AnimatorSet
属性动画是API11加入的属性,可对任何对象做动画,动画默认的时间间隔是300ms,默认帧率10ms/帧,达到的效果是在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。兼容库nineoldandroids,网址:http://nineoldandroid.com,属性动画要求对象
的该属性有get/set方法
ObjectAnimator例子,它是ValueAnimator的子类
ObjectAnimator.ofFloat(myObject,"translationY",-myObject.getHeight).start();
ValueAnimator例子
ValueAnimator colorAnimator=ObjectAnimator.ofInt (this,"backgroundColor",/*RED*/0XFFFF8080,/*RED*/0XFF8080FF); colorAnimator.setDuration(3000); colorAnimator.setEvaluator(new ArgbEvaluator()); colorAnimator.setRepeatCount(ValueAnimator.INFINITE); colorAnimator.setRepeatMode(ValueAnimator.REVERSE); colorAnimator.start();
####AnimatorSet例子
AnimatorSet set=new AnimatorSet(); set.playTogether( ObjectAnimator.ofInt(myView,"rotationX",0,360), ObjectAnimator.ofInt(myView,"rotationY",0,180) ); set.setDuration(5*1000).start();
属性动画通过XML定义,需要定义在res/animator目录下
<set android:ordering="sequentially" xmlns:android="http://schemas.android.com/apk/res/android"><!-- 播放方式,按顺序还是一起播放--> <objectAnimator> </objectAnimator> <animator> </animator><!--ValueAnimator--> </set><!--AnimatorSet-->
插值器和估值器
自定义插值器需要实现Interpolator或者TimeInterpolator,自定义估值算法需要实现TypeEvaluator.另外如果要对其他类型(非int、float、Color)做动画,那么必须要自定义类型估值算法,可参考http://www.weidu8.net/wx/140849。
属性动画的监听器
ValueAnimator.AnimatorUpdateListener
public void onAnimationUpdate(ValueAnimator animation);监听动画的整个过程,每播放一帧就会被调用一次
Animator.AnimatorListener
public void onAnimationStart(Animator animation) ; public void onAnimationEnd(Animator animation); public void onAnimationCancel(Animator animation); public void onAnimationRepeat(Animator animation);
属性动画的要求
1、object必须提供setXX/getXX属性的方法,当没有初始值的时候需要调get方法获取,否则程序cash。2、object提供的setXX所做的改变必须能够通过某种方法反应出来,否则动画无效果。
想要满足上面两条件的话,有3种方法,如下:
1,给你的对象加上get和set方法,如果你有权限的话
2,用一个类来包装原始对象,间接为其提供get和set方法
3,采用ValueAnimator,监听动画的过程,自己实现属性的改变
如下:
package site.zhangyun.appliction; import android.animation.IntEvaluator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.animation.LinearInterpolator; import android.widget.Button; import com.efrobot.library.RobotManager; import com.efrobot.library.RobotState; import com.efrobot.library.task.ControlManager; public class MainActivity extends AppCompatActivity implements View.OnClickListener { Button mBtLight, mBtLightPutout; RobotManager mRobotManager; ObjectAnimator mObjectAnimator; ValueAnimator valueAnimator; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); InitViews(); } void InitViews() { mBtLight = (Button) findViewById(R.id.lightchange); mBtLight.setOnClickListener(this); mBtLightPutout = (Button) findViewById(R.id.light_putout); mBtLightPutout.setOnClickListener(this); mRobotManager = RobotManager.getInstance(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.lightchange: //坑一:android系统里面吧动画设置给关闭了导致播放不了动画,找了一下午的bug,555.... //实现呼吸灯的效果 mObjectAnimator = ObjectAnimator.ofInt(new myTest(mRobotManager, this), "lightBeltBrightness", 0, 255); mObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int currentValue = (Integer) animation.getAnimatedValue(); Log.d("当前灯带亮度", currentValue + ""); } }); mObjectAnimator.setRepeatCount(ValueAnimator.INFINITE);//死循环 mObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);//先从熄灭到亮,再从亮到熄灭 mObjectAnimator.setInterpolator(new LinearInterpolator());//线性变换一次递增 mObjectAnimator.setDuration(1000 * 10);//动画执行时间为10秒 mObjectAnimator.start(); //ValueAnimator实现允许变化从0到255 performAnimator(ControlManager.getInstance(mRobotManager), 0, 255); break; case R.id.light_putout: ControlManager.getInstance(mRobotManager).setLightBeltBrightness(0); if (mObjectAnimator != null) { mObjectAnimator.cancel(); } break; } } void performAnimator(final ControlManager controlManager, final int start, final int end) { valueAnimator = ValueAnimator.ofInt(0, 255); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { private IntEvaluator mEvaluator = new IntEvaluator();//整形估值器,匀速 @Override public void onAnimationUpdate(ValueAnimator animation) { //获取当前动画的进度值 int currentValue = (Integer) animation.getAnimatedValue(); //获取当前的进度占整个动画过程的比例 float fraction = animation.getAnimatedFraction(); //设置灯带的亮度 controlManager.setLightBeltBrightness(mEvaluator.evaluate(fraction, start, end)); //呼吸灯是抛物线,0-255-0,自己算吧y=(-51/5)*t2+102t } }); valueAnimator.setRepeatCount(ValueAnimator.INFINITE); valueAnimator.setRepeatMode(ValueAnimator.REVERSE); valueAnimator.setDuration(1000 * 10).start(); } //ControlManager里面只有set木有get于是乎就得自己实现啦 class myTest extends ControlManager { ControlManager mControlManager; RobotState mRobotState; myTest(RobotManager robotManager, Context context) { super(robotManager); mControlManager = ControlManager.getInstance(mRobotManager); mRobotState = RobotState.getInstance(context); } public int getLightBeltBrightness() { return mRobotState.getLightBeltBrightness(); } public void setLightBeltBrightness(int lightBeltBrightness) { mControlManager.setLightBeltBrightness(lightBeltBrightness); } } @Override protected void onDestroy() { super.onDestroy(); //这里要是不调用的话,就会内存泄漏 //当动画为无限循环动画的时候,动画持有view,view持有activity,那么activity无法释放,内存泄漏 if (mObjectAnimator != null) { mObjectAnimator.cancel(); } if (valueAnimator != null) { valueAnimator.cancel(); } } }
使用动画的注意事项
1、当图片的数量过多较大时极易容易出现OOM,开发中应尽量避免。2、无限循环属性动画容易造成内存泄漏,需要在activity退出时及时停止,view动画不存在此问题。
3、view动画是对view的影像做动画,并不是真的改变状态,有时出现动画完成后view无法隐藏问题,可以先调用view.clearAnimation()。
4、进行动画时尽可能使用dp,px会导致在不同设备有不同效果
5、从3.0开始,属性动画的单击事件触发位置为移动后的位置,但view动画任然在原位置。
6,开启硬件加速可以提高动画流畅性
7,动画在3.0以下有兼容问题
相关文章推荐
- 第七章Andorid动画深入分析(Android开发艺术探索)
- 【读书笔记】【Android 开发艺术探索】第 7 章 Android 动画深入分析
- Android 开发艺术探索笔记 第七章 Android动画深入分析
- Android开发艺术探索__android动画深入分析(七)
- Android开发艺术探索——第七章:Android动画深入分析
- Android动画开发——Animation动画效果
- Android动画开发——Animation动画效果
- Android UI开发第十二篇——动画效果Animation(一)
- 【Android2D游戏开发十四】(未完待续)手把手教你在SurfaceView中照样使用Android 动画—Tween Animation!
- Android动画开发——Animation动画效果
- [转]Android动画开发——Animation动画效果
- android开发(9) 渐变动画演示(Tween Animation)
- Android动画开发——Animation动画效果
- <转>Android动画开发—Animation动画效果详解
- Android动画开发——Animation动画效果
- Android动画开发——Animation动画效果
- Android动画开发——Animation动画效果
- Android动画开发——Animation动画效果
- Android动画开发——Animation动画效果
- Android动画开发——Animation动画效果