基本的补间动画分为四个(透明度,缩放,位移,旋转)
<set>标签对应表示动画集合,对应AnimationSet,他可以包含若干个动画,并且它的内部也是嵌套其他动画的集合,它的两个属性的含义如下:
android:interpolator 表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过设置插值器来控制动画的播放过程,这个属性可以不指定,默认为android:anim/accelerate_decelerate_interpolator,即加速减速插值器,关于这个概念后面有篇专门讲这个的文章点我看interpolator
表示集合中的动画是否和集合共享同一个插值器
· android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
· android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
· android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
· android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,
当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;
如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;
如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。(具体意义,后面会举例演示)
· android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
默认轴点是是View的中心· android:duration 动画持续时间,以毫秒为单位
· android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态(这里的结束指的是自然播放的结束不是手动cancel)
· android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态(这里的结束指的是自然播放的结束不是手动cancel)
· android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
· android:repeatCount 重复次数
· android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
· android:interpolator 设定插值器,其实就是指定的动作效果,后面会讲。
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener, Animation.AnimationListener { private ImageView iv; private AlphaAnimation alphaAnimation; private ScaleAnimation scaleAnimation; private TranslateAnimation transAnimation; private RotateAnimation rotateAnimation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.bt_alpha).setOnClickListener(this); findViewById(R.id.bt_rotate).setOnClickListener(this); findViewById(R.id.bt_scale).setOnClickListener(this); findViewById(R.id.bt_tran).setOnClickListener(this); findViewById(R.id.bt_set).setOnClickListener(this); findViewById(R.id.bt_stop).setOnClickListener(this); iv = (ImageView) findViewById(R.id.iv); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.bt_alpha: alphaAnimation = new AlphaAnimation(0.0f,0.5f); //持续时间长度 alphaAnimation.setDuration(2000); //最后是最终的样子(保持 true,既保持动画最后的效果) alphaAnimation.setFillAfter(true); //设置持续册数(总共播放次数 变成3!!!!) alphaAnimation.setRepeatCount(2); //重复的模式//有无限,相反 alphaAnimation.setRepeatMode(Animation.REVERSE); iv.startAnimation(alphaAnimation); //监听动画的开始结束 alphaAnimation.setAnimationListener(this); break; case R.id.bt_scale: //最后是放大缩小的中心点 //public ScaleAnimation (float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) //Animation.RELATIVE_TO_SELF (指的是后面的参数相对于谁) 0.5 就相当于百分之50 1就相当于百分之100 scaleAnimation = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //持续时间长度 scaleAnimation.setDuration(2000); //最后是最终的样子(保持 true,既保持动画最后的效果) scaleAnimation.setFillAfter(false); //设置持续册数 scaleAnimation.setRepeatCount(2); //重复的模式//有无限,相反 //scaleAnimation.setRepeatMode(Animation.REVERSE); iv.startAnimation(scaleAnimation); //监听动画的开始结束 scaleAnimation.setAnimationListener(this); break; case R.id.bt_tran: transAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f, Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0.5f); //持续时间长度 transAnimation.setDuration(2000); //最后是最终的样子(保持 true,既保持动画最后的效果) transAnimation.setFillAfter(true); //设置持续册数 transAnimation.setRepeatCount(2); //重复的模式//有无限,相反 transAnimation.setRepeatMode(Animation.REVERSE); iv.startAnimation(transAnimation); //监听动画的开始结束 transAnimation.setAnimationListener(this); break; case R.id.bt_rotate: //感觉这里的relative_parent不像是相对屏幕,看清楚到底是相对谁???????? rotateAnimation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); //持续时间长度 rotateAnimation.setDuration(2000); //最后是最终的样子(保持 true,既保持动画最后的效果) rotateAnimation.setFillAfter(true); //设置持续册数 rotateAnimation.setRepeatCount(2); //重复的模式//有无限,相反 rotateAnimation.setRepeatMode(Animation.REVERSE); iv.startAnimation(rotateAnimation); //监听动画的开始结束 rotateAnimation.setAnimationListener(this); break; case R.id.bt_set: //Pass true if all of the animations in this set should use // the interpolator associated with this AnimationSet. // Pass false if each animation should use its own interpolator. AnimationSet set = new AnimationSet(true); TranslateAnimation ta = new TranslateAnimation( Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ta.setDuration(2000); ta.setRepeatCount(2); ta.setRepeatMode(Animation.REVERSE); RotateAnimation ra = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(2000); ra.setRepeatCount(2); ra.setRepeatMode(Animation.REVERSE); ScaleAnimation sa = new ScaleAnimation(0.0f, 2.0f, 0.0f, 2.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(2000); sa.setRepeatCount(2); sa.setRepeatMode(Animation.REVERSE); set.addAnimation(sa); set.addAnimation(ta); set.addAnimation(ra); iv.startAnimation(set); break; case R.id.bt_stop: //停止所有动画 iv.clearAnimation(); break; } } @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } }
复杂版源码
MainActivity.java
public class MainActivity extends Activity implements View.OnClickListener, Animation.AnimationListener { private ImageView iv; private Animation scale; private Animation trans; private Animation rotate; private Animation alpha; private Animation set; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); findViewById(R.id.bt_alpha).setOnClickListener(this); findViewById(R.id.bt_rotate).setOnClickListener(this); findViewById(R.id.bt_scale).setOnClickListener(this); findViewById(R.id.bt_tran).setOnClickListener(this); findViewById(R.id.bt_set).setOnClickListener(this); findViewById(R.id.bt_stop).setOnClickListener(this); iv = (ImageView) findViewById(R.id.iv); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.bt_alpha: alpha = AnimationUtils.loadAnimation(this, R.anim.alpha); iv.startAnimation(alpha); break; case R.id.bt_scale: scale = AnimationUtils.loadAnimation(this, R.anim.scale); iv.startAnimation(scale); break; case R.id.bt_tran: trans = AnimationUtils.loadAnimation(this, R.anim.trans); iv.startAnimation(trans); break; case R.id.bt_rotate: rotate = AnimationUtils.loadAnimation(this, R.anim.rotate); iv.startAnimation(rotate); break; case R.id.bt_set: set = AnimationUtils.loadAnimation(this, R.anim.set); iv.startAnimation(set); break; case R.id.bt_stop: //停止所有动画 iv.clearAnimation(); break; } } @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { } }
alaph.xml
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:fromAlpha="0" android:toAlpha="1.0" android:duration="2000" android:repeatCount="2" android:repeatMode="reverse" > </alpha>
//rotate.xml(里面P,是代表父控件的意思,没有P,就是指自身)
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="90" android:toDegrees="0" android:duration="2000" android:repeatCount="2" android:repeatMode="reverse" android:pivotX="20%p" android:pivotY="20%p" > </rotate>scale.xml
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXScale="0.0" android:fromYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="2" android:repeatMode="reverse" android:toXScale="2.0" android:toYScale="2.0" > </scale>tran.xml
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXDelta="-50%p" android:fromYDelta="0%" android:repeatCount="2" android:repeatMode="reverse" android:toXDelta="0%" android:fillAfter="true" android:toYDelta="50%" > </translate>set.xml
<?xml version="1.0" encoding="utf-8"?> <set> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="2" android:repeatMode="reverse" android:toDegrees="360" > </rotate> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXScale="0.0" android:fromYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:repeatCount="2" android:repeatMode="reverse" android:toXScale="2.0" android:toYScale="2.0" > </scale> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fromXDelta="-50%" android:fromYDelta="-50%" android:repeatCount="2" android:repeatMode="reverse" android:toXDelta="50%" android:toYDelta="50%" > </translate> </set>
简单版源码
Rotate.xml(圆心以parent的宽高的1/3)
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="-360" android:duration="2000" android:repeatCount="2" android:repeatMode="reverse" android:pivotX="30%p" android:pivotY="30%p" > </rotate>
Rotate.xml(圆心以parent的宽高的1/3)
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="-360" android:duration="2000" android:repeatCount="2" android:repeatMode="reverse" android:pivotX="50%" android:pivotY="50%" > </rotate>
<1>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="180" android:duration="2000" android:fillAfter="true" android:pivotX="50%" android:pivotY="50%" > </rotate><2>
<rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" android:toDegrees="-180" android:duration="2000" android:fillAfter="true" android:pivotX="50%" android:pivotY="50%" > </rotate>
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/girl_1" android:duration="100"/> <item android:drawable="@drawable/girl_2" android:duration="100"/> <item android:drawable="@drawable/girl_3" android:duration="100"/> <item android:drawable="@drawable/girl_4" android:duration="100"/> <item android:drawable="@drawable/girl_5" android:duration="100"/> <item android:drawable="@drawable/girl_6" android:duration="100"/> <item android:drawable="@drawable/girl_7" android:duration="100"/> <item android:drawable="@drawable/girl_8" android:duration="100"/> <item android:drawable="@drawable/girl_9" android:duration="100"/> <item android:drawable="@drawable/girl_10" android:duration="100"/> <item android:drawable="@drawable/girl_11" android:duration="100"/> </animation-list>
public class MainActivity extends AppCompatActivity { private Button bt_one; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_one = (Button) findViewById(R.id.bt_one); } public void startAnimation(View view){ bt_one.setBackgroundResource(R.drawable.frame_animation); AnimationDrawable drawable = (AnimationDrawable) bt_one.getBackground(); drawable.start(); } }
(1).效果图
(2)主要代码
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private ImageView iv_slow; private ImageView iv_faster; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iv_slow = (ImageView) findViewById(R.id.img_home_cloud_move_slower); iv_faster = (ImageView) findViewById(R.id.img_home_cloud_move_faster); findViewById(R.id.bt_start).setOnClickListener(this); } @Override public void onClick(View v) { if(v.getId() == R.id.bt_start){ Animation slower = AnimationUtils.loadAnimation(this,R.anim.home_cloud_animation_slower); iv_slow.startAnimation(slower); Animation faster = AnimationUtils.loadAnimation(this,R.anim.home_cloud_animation_fater); iv_faster.startAnimation(faster); } } }
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="100%p" android:toXDelta="-20%p" android:interpolator="@android:anim/linear_interpolator" android:repeatCount="infinite" android:duration="30000" /> </set>
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="100%p" android:toXDelta="-20%p" android:interpolator="@android:anim/linear_interpolator" android:repeatCount="infinite" android:duration="20000" /> </set>
LayoutAnimation给ViewGroup指定一个动画,那么他的子View也会是这个动画
anim_layout.xml
<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:delay = "0.5" android:animationOrder="random" android:animation = "@anim/anim_item"/>
<!--android:delay = "10" 這個10 指的是anim_item中duration的倍數,這裡就相當於10*0.3 = 3 相当于每隔3s就播放一次动画--> <!--android:animationOrder="random" 有三种normal reverse random 其中normal:按顺序显示 ,既前面的条目先播放 其中reverse:既排在后面的子元素先开始播放入场动画 random 则是随机播放入场动画-->
android:animation 为子元素指定具体的入场动画
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="300" android:shareInterpolator="true" android:interpolator="@android:anim/accelerate_interpolator"> <alpha android:fromAlpha="0.0" android:toAlpha="1.0"/> <translate android:fromXDelta="500" android:toXDelta="0" /> </set>
<ListView android:id="@+id/lv" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layoutAnimation="@anim/anim_layout"> </ListView>
Animation animation = AnimationUtils.loadAnimation(this,R.anim.anim_item); LayoutAnimationController controller = new LayoutAnimationController(animation); controller.setDelay(0.3f); controller.setOrder(LayoutAnimationController.ORDER_RANDOM); lv.setLayoutAnimation(controller);
LayoutAnimation基本使用的源码
Activity有默认的切换效果,但是这个效果我们可以自定义的,主要用到overridePendingTransition(int enterAnim,int exitAnim)这个方法,这个方法必须在startActivity或者finish()之后调用才能生效(否则无效)。
BaseActivity.java
public abstract class BaseActivity extends Activity { private GestureDetector mGestureDetector; public SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_base); sp = getSharedPreferences("config", MODE_PRIVATE); //完成手势滑动 //SimpleOnGestureListener//相当于阉割版 // A convenience class to extend when you only want to listen for a subset of all the gestures. // This implements all methods in the OnGestureListener and OnDoubleTapListener // but does nothing and return false for all applicable methods mGestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //首先先排除无效动作,比如数值方向滑动//我们要求尽可能的水平滑动 if (e1.getRawY() - e2.getRawY() > 100) { Toast.makeText(BaseActivity.this, "请正确姿势滑动。。。水平滑动!!!", Toast.LENGTH_SHORT).show(); return true; } //判断如果是左<--------右 if (e1.getRawX() - e2.getRawX() > 150) { showNext(); overridePendingTransition(R.anim.tran_next_in, R.anim.tran_next_out); return true; } //判断如果是左------->右 if (e2.getRawX() - e1.getRawX() > 150) { showPre(); overridePendingTransition(R.anim.tran_pre_in, R.anim.tran_pre_out); return true; } return super.onFling(e1, e2, velocityX, velocityY); } }); } @Override public boolean onTouchEvent(MotionEvent event) { //别忘了这个 mGestureDetector.onTouchEvent(event); return super.onTouchEvent(event); } /** * 给出上下两个函数让子类继承然后覆写功能 */ public abstract void showNext(); public abstract void showPre(); /** * 让子类直接继承调用就行 * 功能showNext() * 动画overridePendingTransition * 不要忘了写View view */ public void next(View view) { showNext(); overridePendingTransition(R.anim.tran_next_in, R.anim.tran_next_out); } /** * 让子类直接继承调用就行 * 功能showNext() * 动画overridePendingTransition * 不要忘了写View view */ public void pre(View view) { showPre(); overridePendingTransition(R.anim.tran_pre_in, R.anim.tran_pre_out); } }
tran_next_in.xml
<?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="300" > </translate>
MainActivity.java
public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public void showNext() { Intent intent = new Intent(this,SecondActivity.class); startActivity(intent); } @Override public void showPre() { Toast.makeText(MainActivity.this,"到头了",Toast.LENGTH_SHORT).show(); } }
源码在这