Android动画(一)
2015-12-30 18:24
381 查看
(《群英传》)笔记:
1、视图动画
动画实现原理:每次绘制视图时,View所在的ViewGroup中drawChild函数获取该View的Animation的Transformation值,调用canvans.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧。如果动画没有完成,就继续调用invalidate()函数,启动下次绘制来驱动动画,从而完成整个动画的绘制。
特点:不能实现交互,元素发生视图动画后,其响应的事件依然在动画前的地方。但效率比较高且使用方便。
四种动画方式:
(1) 透明度动画(Alpha):
(2)旋转动画(Rotate):
位移动画(TranslateAnimation):
缩放动画(Scale):
动画集合:
通过AnimationSet,可以将动画以组合形式展现出来:
对应的动画事件监听回调:
2、 属性动画:
原理:属性动画调用属性的get、set方法来真实地控制了一个View的属性值。通过对AnimatorSet和ObjectAnimator进行精细化控制的配合,只控制一个对象的一个属性值,而使用多个ObjectAnimator组合到AnimatorSet形成一个动画。ObjectAnimator调用setFrameDelay(longframeDelay)设置动画帧之间的间隙时间,调整帧率,减少动画过程中频繁绘制界面,在不影响动画效果的前提下减少CPU的资源消耗。
(1)ObjectAnimator
基本用法:
可以直接使用属性动画的属性值:
translationX和translationY:控制View对象从他的布局容器左上角坐标偏移的位置;
rotation、rotationX和rotationY:控制View对象围绕支点进行2D和3D旋转;
scaleX和scaleY:控制View对象围绕它的支点进行2D缩放;
x和y:描述了View对象在它的容器中的最终位置,它是最初的左上角坐标和translationX和translationY值得累计和;
alpha:它表示View对象的alpha透明度。默认值是1(不透明),0代表完全透明(不可见)。
如果一个属性没有get、set方法。可以通过ValueAnimator来实现。
(2)ValueAnimator
ObjectAnimator是继承自ValueAnimator的。ValueAnimator本身不提供任何动画效果,用来产生具有一定规律的数字,从而让调用者来控制动画的实现效果。
(3)PropertyValuesHolder:
组合动画。比如一个动画在平移过程中,同时改变X、Y轴的缩放。
动画事件的监听
(5)AnimatorSet
不仅能实现PropertyValuesHolder的效果,也能实现更为精确的顺序控制。
(6)在XML中使用动画:
在程序中使用XML定义的属性动画:
(7)View的animate方法:
直接驱动属性动画。是属性动画的一种简写方式。
3、布局动画
作用在ViewGroup上,给ViewGroup增加View时添加一个动画过渡效果。
(1)最简单的布局动画:
(2)使用LayoutAnimationController 类来自定义一个子View的过渡效果。
示例:子View出现的时候,有一个缩放的动画效果。
ORDER_NORMAL:顺序
ORDER_RANDOM:随机
ORDER_REVERSE:反序
4、 Interpolators(插值器)
可以定义动画变换速率,类似加速度,作用是控制目标变量的变化值进行对应的变化。
5、自定义动画
只需要实现它的applyTransformation的逻辑就可以了。
模拟电视机关闭的效果:让一个图片纵向比例不断缩小。
7、Android动画特效
示例1:灵动菜单
思路:使用属性动画,每个不同的按钮设置不同的动画,并设置相应的插值器实现展开、合拢效果。
示例2:计时器(使用ValueAnimator)
1、视图动画
动画实现原理:每次绘制视图时,View所在的ViewGroup中drawChild函数获取该View的Animation的Transformation值,调用canvans.concat(transformToApply.getMatrix()),通过矩阵运算完成动画帧。如果动画没有完成,就继续调用invalidate()函数,启动下次绘制来驱动动画,从而完成整个动画的绘制。
特点:不能实现交互,元素发生视图动画后,其响应的事件依然在动画前的地方。但效率比较高且使用方便。
四种动画方式:
(1) 透明度动画(Alpha):
AlphaAnimation aa = new AlphaAnimation(0, 1); aa.setDuration(1000); view.startAnimation(aa);
(2)旋转动画(Rotate):
// 起始角度、旋转中心坐标 RotateAnimation ra = new RotateAnimation(0, 360, 100, 100); ra.setDuration(1000); view.startAnimation(ra);
位移动画(TranslateAnimation):
// (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300); ta.setDuration(1000); view .startAnimation(ta);
缩放动画(Scale):
// (float fromX, float toX, float fromY, float toY) ScaleAnimation sa = new ScaleAnimation(0, 2, 0, 2); sa.setDuration(1000); view.startAnimation(sa);
动画集合:
通过AnimationSet,可以将动画以组合形式展现出来:
AnimationSet as = new AnimationSet(true); as.setDuration(1000); AlphaAnimation aa = new AlphaAnimation(0, 1); aa.setDuration(1000); as.addAnimation(aa); TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300); ta.setDuration(1000); as.addAnimation(ta);
对应的动画事件监听回调:
// 可以获取到动画的开始、结束合重复事件,并针对相应的事件作出不同的处理。 animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } });
2、 属性动画:
原理:属性动画调用属性的get、set方法来真实地控制了一个View的属性值。通过对AnimatorSet和ObjectAnimator进行精细化控制的配合,只控制一个对象的一个属性值,而使用多个ObjectAnimator组合到AnimatorSet形成一个动画。ObjectAnimator调用setFrameDelay(longframeDelay)设置动画帧之间的间隙时间,调整帧率,减少动画过程中频繁绘制界面,在不影响动画效果的前提下减少CPU的资源消耗。
(1)ObjectAnimator
基本用法:
// 操纵的View; 操纵的属性; 可变数组参数,该属性变化的一个取值过程。 ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationX", 300);
可以直接使用属性动画的属性值:
translationX和translationY:控制View对象从他的布局容器左上角坐标偏移的位置;
rotation、rotationX和rotationY:控制View对象围绕支点进行2D和3D旋转;
scaleX和scaleY:控制View对象围绕它的支点进行2D缩放;
x和y:描述了View对象在它的容器中的最终位置,它是最初的左上角坐标和translationX和translationY值得累计和;
alpha:它表示View对象的alpha透明度。默认值是1(不透明),0代表完全透明(不可见)。
如果一个属性没有get、set方法。可以通过ValueAnimator来实现。
(2)ValueAnimator
ObjectAnimator是继承自ValueAnimator的。ValueAnimator本身不提供任何动画效果,用来产生具有一定规律的数字,从而让调用者来控制动画的实现效果。
// ValueAnimator的一般使用方法 ValueAnimator animator = ValueAnimator.ofFloat(0, 100); animator.setTarget(view); animator.setDuration(1000).start(); animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Float value = (Float) animation.getAnimatedValue(); // TODO use the value } });
(3)PropertyValuesHolder:
组合动画。比如一个动画在平移过程中,同时改变X、Y轴的缩放。
PropertyValuesHolder pHolder1 = PropertyValuesHolder.ofFloat("translationX", 300f); PropertyValuesHolder pHolder2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f); PropertyValuesHolder pHolder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f); ObjectAnimator.ofPropertyValuesHolder(view, pHolder1, pHolder2, pHolder3).setDuration(1000);
动画事件的监听
ObjectAnimator anim = ObjectAnimator.ofFloat(view, "alpha", 0.5f); anim.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } // 大部分时候只关心onAnimationEnd动画 @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } }); anima.start(); Android提供了AnimatorListenerAdapter来让我们选择必要的事件进行监听。 anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } });
(5)AnimatorSet
不仅能实现PropertyValuesHolder的效果,也能实现更为精确的顺序控制。
ObjectAnimator anim1 = ObjectAnimator.ofFloat(view, "translationX", 300f); ObjectAnimator anim2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f); ObjectAnimator anim3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); // 通过playTogether()、playSequentially()、animSet.play().with()、before()、after() // 这些方法来控制多个动画的协同工作方式。 set.playTogether(anim1, anim2, anim3); set.start();
(6)在XML中使用动画:
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="2.0" android:valueType="floatType" > </objectAnimator>
在程序中使用XML定义的属性动画:
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.property); animator.setTarget(view); animator.start();
(7)View的animate方法:
直接驱动属性动画。是属性动画的一种简写方式。
view.animate().alpha(0).y(300).setDuration(1000) .withStartAction(new Runnable() { @Override public void run() { } }).withEndAction(new Runnable() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { } }); } });
3、布局动画
作用在ViewGroup上,给ViewGroup增加View时添加一个动画过渡效果。
(1)最简单的布局动画:
Android:animateLayoutChanges="true"
(2)使用LayoutAnimationController 类来自定义一个子View的过渡效果。
示例:子View出现的时候,有一个缩放的动画效果。
LinearLayout ll = findViewById(R.id.ll); //设置过渡动画 ScaleAnimation sa = new ScaleAnimation(0, 1 ,0, 1); sa.setDuration(1000); // 设置布局动画的显示属性 LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F); lac.setOrder(LayoutAnimationController.ORDER_NORMAL); // 为ViewGroup设置布局动画 ll.setLayoutAnimation(lac);
ORDER_NORMAL:顺序
ORDER_RANDOM:随机
ORDER_REVERSE:反序
4、 Interpolators(插值器)
可以定义动画变换速率,类似加速度,作用是控制目标变量的变化值进行对应的变化。
5、自定义动画
只需要实现它的applyTransformation的逻辑就可以了。
public class CustomAnim extends Animation { private int mCenterWidth; private int mCenterHeight; // Camera 封装了openGL的3D动画 private Camera mCamera = new Camera(); private float mRotateY = 0.0f; @Override public void initialize(int width, int height, int parentWidth, int parentHeight) { super.initialize(width, height, parentWidth, parentHeight); // 设置默认时长 setDuration(2000); // 动画结束后保留状态 setFillAfter(false); // 设置默认插值器 setInterpolator(new BounceInterpolator()); mCenterWidth = width / 2; mCenterHeight = height / 2; } // 暴露接口-设置旋转角度 public void setRotateY(float rotateY) { mRotateY = rotateY; } // 自定义动画的核心-----如何定义动画的进行过程 //第一个参数:插值器的时间因子0~1.0, 第二个参数:矩阵的封装类。 @Override protected void applyTransformation( float interpolatedTime, Transformation t) { final Matrix matrix = t.getMatrix(); mCamera.save(); // 使用Camera设置旋转的角度 mCamera.rotateY(mRotateY * interpolatedTime); // 将旋转变换作用到matrix上 mCamera.getMatrix(matrix); mCamera.restore(); // 通过matrix的各种操作来实现动画 // 通过pre方法设置矩阵作用前的偏移量来改变旋转中心 matrix.preTranslate(mCenterWidth, mCenterHeight); matrix.postTranslate(-mCenterWidth, -mCenterHeight); } }
模拟电视机关闭的效果:让一个图片纵向比例不断缩小。
Final Matrix matrix = t.getMartrix(); matrix.preScale(1, 1 - interpolatedTime, // 缩放的中心点 mCenterWidth, mCenterHeight);
7、Android动画特效
示例1:灵动菜单
思路:使用属性动画,每个不同的按钮设置不同的动画,并设置相应的插值器实现展开、合拢效果。
/** * 点击主菜单向四周展出子菜单的动画 * @author Administrator * */ public class PropertyTest extends Activity implements View.OnClickListener { private int[] mRes = {R.id.imageView_a, R.id.imageView_b, R.id.imageView_c, R.id.imageView_d, R.id.imageView_e}; private List<ImageView> mImageViews = new ArrayList<ImageView>(); private boolean mFlag = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.property); for (int i = 0; i < mRes.length; i++) { ImageView imageView = (ImageView) findViewById(mRes[i]); imageView.setOnClickListener(this); mImageViews.add(imageView); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.imageView_a: if (mFlag) { startAnim(); } else { closeAnim(); } break; default: Toast.makeText(PropertyTest.this, "哈哈" + v.getId(), Toast.LENGTH_SHORT).show(); break; } } private void closeAnim() { ObjectAnimator animator0 = ObjectAnimator.ofFloat(mImageViews.get(0), "alpha", 0.5F, 1F); ObjectAnimator animator1 = ObjectAnimator.ofFloat(mImageViews.get(1), "translationY", 200F, 0); ObjectAnimator animator2 = ObjectAnimator.ofFloat(mImageViews.get(2), "translationX", 200F, 0); ObjectAnimator animator3 = ObjectAnimator.ofFloat(mImageViews.get(3), "translationY", -200F, 0); ObjectAnimator animator4 = ObjectAnimator.ofFloat(mImageViews.get(4), "translationX", -200F, 0); AnimatorSet set = new AnimatorSet(); set.setDuration(500); set.setInterpolator(new BounceInterpolator()); set.playTogether(animator0, animator1, animator2, animator3, animator4); set.start(); mFlag = true; } private void startAnim() { ObjectAnimator animator0 = ObjectAnimator.ofFloat( mImageViews.get(0), "alpha", 1F, 0.5F); ObjectAnimator animator1 = ObjectAnimator.ofFloat( mImageViews.get(1), "translationY", 200F); ObjectAnimator animator2 = ObjectAnimator.ofFloat( mImageViews.get(2), "translationX", 200F); ObjectAnimator animator3 = ObjectAnimator.ofFloat( mImageViews.get(3), "translationY", -200F); ObjectAnimator animator4 = ObjectAnimator.ofFloat( mImageViews.get(4), "translationX", -200F); AnimatorSet set = new AnimatorSet(); set.setDuration(500); set.setInterpolator(new BounceInterpolator()); set.playTogether( animator0, animator1, animator2, animator3, animator4); set.start(); mFlag = false; } }
示例2:计时器(使用ValueAnimator)
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:onClick="onClick" android:text="点我!!" android:textSize="60sp" /> </RelativeLayout> /** * 计时器 * @author Administrator * */ public class TimerTest extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.timer); } public void onClick(final View view) { ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100); valueAnimator.addUpdateListener( new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { // 借助ValueAnimator来实现数字的不断增加,并将值设置给TextView ((TextView) view).setText("$ " + (Integer) animation.getAnimatedValue()); } }); valueAnimator.setDuration(3000); valueAnimator.start(); } }
相关文章推荐
- Android中Menu的基本用法
- Android 下雪动画
- 说说arcGIS for Android
- android 消息推送机制之GCM(二)
- android 时间戳转换成字符串时24小时制与12小时制的区别
- android 消息推送机制之GCM(一)
- android开发技巧——仿新版QQ锁屏下弹窗
- Android 6.0 Changes
- Android之JAVASe基础篇-面向对象-多线程(七)
- Android Studio你不知道的调试技巧
- android自定义style
- Android混淆
- layer-list(图层叠加)
- Android开源项目大全 - 工具类
- Mac环境下Android Studio jni开发调用 javah编译不了头文件问题
- Android studio 自定义打包APK名称
- 《Monkey Android》第11课Button和ImageButton
- Android应用开发--MP3音乐播放器代码实现(一)
- Android开源项目大全 - 博客类
- Android自定义Dialog样式,从屏幕底部滑出动画