一直对画画相关不感冒,但是Android的动画机制还是要硬着头皮拿下
先看看各种动画的效果,界面很丑
Android提供了AlphaAnimation,RotateAnimatio,TranslateAnimation,ScaleAnimation四种动画方式,并提供了Animationset动画集合,混合使用多种动画,有动画肯定就有动画在各个状态的监听
case R.id.alpha:// 透明动画 AlphaAnimation al = new AlphaAnimation(0, 1); al.setDuration(2000); alpha.startAnimation(al); // 动画监听 al.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { Log.i("slack", "onAnimationStart"); } @Override public void onAnimationEnd(Animation animation) { Log.i("slack", "onAnimationEnd"); Toast.makeText(MainActivity.this, "动画结束", Toast.LENGTH_LONG).show(); } @Override public void onAnimationRepeat(Animation animation) { Log.i("slack", "onAnimationRepeat"); } }); break; case R.id.rotate:// 旋转动画 // RotateAnimation (float fromDegrees, float toDegrees, float pivotX, float pivotY) RotateAnimation ro = new RotateAnimation(0, 180, 100, 100); ro.setDuration(2000); // rotate.setAnimation(ro); rotate.startAnimation(ro); break; case R.id.translate: // 平移动画 // TranslateAnimation (float fromXDelta, float toXDelta, float fromYDelta, float toYDelta) TranslateAnimation tr = new TranslateAnimation(0, 200, 0, 300); tr.setDuration(2000); // translate.setAnimation(tr); // want the animation to play immediately translate.startAnimation(tr); tr.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { // 再移回来 TranslateAnimation tr = new TranslateAnimation(200, 0, 300, 0); tr.setDuration(2000); translate.startAnimation(tr); } @Override public void onAnimationRepeat(Animation animation) { } }); break; case R.id.scale:// 缩放动画 // ScaleAnimation (float fromX, float toX, float fromY, float toY) ScaleAnimation sc = new ScaleAnimation(0, 2, 0, 2); sc.setDuration(2000); scale.startAnimation(sc); break; case R.id.set:// AnimationSet 动画集合 AnimationSet setAnimation = new AnimationSet(true); setAnimation.setDuration(2000); AlphaAnimation als = new AlphaAnimation(0, 1); als.setDuration(2000); setAnimation.addAnimation(als); RotateAnimation ros = new RotateAnimation(0, 360, 100, 100); ros.setDuration(2000); setAnimation.addAnimation(ros); ScaleAnimation scs = new ScaleAnimation(0, 1, 0, 1); scs.setDuration(2000); setAnimation.addAnimation(scs); set.startAnimation(setAnimation); break;ObjectAnimator
case R.id.object:// 使用ObjectAnimator进行更精细化的控制,操作单个属性 /** * translationX和 translationY:这两个属性作为一种增量来控制着View对象从它布局容器的左上角坐标偏移的位置。 * rotation、rotationX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转 * scaleX和scaleY. 这两个属性控制着View对象围绕它的支点进行2D缩放。 * pivotX和pivotY:这两个属性控制着view对象的支点位置,围绕这个支点进行旋转和缩放变换处理, 默认情况下,该支点的位置就是View对象的中心点。 * x和y这是两个简单实用的属性,它描述了View对象在它的容器中的最终位置, 它是最初的左上角坐标和 translationX和 translationY值的累计和 * alpha:它表示View对象的alpha透明度,默认值是1(不透明),0代表完全透明(不可见) * 需要注意的是,这里操作的属性要有 set,get的方法,如果自己自定义一个动画类,需要提供属性的get/set方法 * */ ObjectAnimator ob = ObjectAnimator.ofFloat(object, "translationX", 300); ob.setDuration(2000); ob.start(); ob.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { // 还原 ObjectAnimator.ofFloat(object, "translationX", 0).setDuration(2000).start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); break;PropertyValuesHolder
case R.id.property:// 类似视图动画中的AnimationSet,就是把动画给组合起来 PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("rotation",30);// 30° PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX",1f,0,1.2f); PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY",1f,1,1f);// 属性,开始变化的大小,是否变化到最小(1 no, 0 yes),结束变化后的大小 ObjectAnimator.ofPropertyValuesHolder(property,pvh1,pvh2,pvh3).setDuration(2000).start(); // ObjectAnimator.ofPropertyValuesHolder(property,pvh3).setDuration(2000).start(); break;ValueAnimator
case R.id.value:// ObjectAnimator也是继承自ValueAnimator //ValueAnimator本身不提供任何动画,他更像是一个数值发生器, // 用来产生一定具有规律的数字,从而让调用者控制动画的整个过程 ValueAnimator va = ValueAnimator.ofFloat(0, 50); va.setTarget(value); va.setDuration(2000).start(); va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float values = (float) animation.getAnimatedValue(); Log.i("slack", "values:"+values ); } }); //只监听动画结束 va.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); Log.i("slack", "done..." ); } }); break;AnimatorSet
case R.id.animatorSet:// 对于一个属性同时作用在一个view上,跟PropertyValuesHolder一样,但是AnimatorSet不仅能实现,而且能更精准的控制顺序 ObjectAnimator animator1 = ObjectAnimator.ofFloat(animatorSet, "rotation", 30); ObjectAnimator animator2 = ObjectAnimator.ofFloat(animatorSet, "scaleX", 1f, 0, 2f); ObjectAnimator animator3 = ObjectAnimator.ofFloat(animatorSet, "scaleY", 1f, 0, 1f); AnimatorSet set = new AnimatorSet(); set.setDuration(2000); // set.playTogether(animator1, animator2, animator3);// 通过playTogether等方法控制多个动画协同工作,从而控制播放顺序 set.playSequentially(animator1, animator2, animator3);// 依次动画 set.start(); break;animate
case R.id.animate:// animate方法直接来驱动属性动画 animate.animate().alpha(0).y(300).x(100).setDuration(2000).withStartAction(new Runnable() { @Override public void run() { } }).withEndAction(new Runnable() { @Override public void run() { } }).start(); break;使用XML 文件定义动画res/animator/animator.xml
<?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:propertyName="scaleX" android:valueFrom="1.0" android:valueTo="2.0" android:valueType="floatType"> </objectAnimator>java调用
case R.id.fromXML:// 属性动画同样的可以定义在xml Animator anim = AnimatorInflater .loadAnimator(this, R.animator.animator); anim.setTarget(fromXML); anim.start();android 里 使用 SVG
SVG命令详解:
M (x y) 移动到x,y
L (x y) 直线连到x,y,还有简化命令H(x) 水平连接、V(y)垂直连接
Z,没有参数,连接起点和终点
C(x1 y1 x2 y2 x y),控制点x1,y1 x2,y2,终点x,y
Q(x1 y1 x y),控制点x1,y1,终点x,y
A(rx ry x-axis-rotation large-arc-flag sweep-flag x y)
rx ry 椭圆半径
x-axis-rotation x轴旋转角度
large-arc-flag 为0时表示取小弧度,1时取大弧度
sweep-flag 0取逆时针方向,1取顺时针方向
有个图解:
在线 SVG 编辑器:http://editor.method.ac/
使用SVG官方有说明:https://developer.android.com/reference/android/graphics/drawable/AnimatedVectorDrawable.html
主要需要三个文件:
1.VectorDrawable定义的是一张静态图,
2.AnimatedVectorDrawable,可以让矢量图有动画效果,
3.定义动画文件
gitHub上有一个使用SVG 的很好的例子,我就是参考的这个:https://gist.github.com/nickbutcher/b3962f0d14913e9746f2,作者少传里几个文件,我修改了一下,代码里添加了一些注释,原作者的成果,效果就是上面的图里的效果,有需要的可以下载源码。最后是一个下拉动画,使用的是ValueAnimator,使用其产生一定具有规律的数字来实现淡出和淡入效果
附件:源码:https://github.com/CL-window/animations