优秀文章:
HenCoder Android 自定义 View 1-6: 属性动画(上手篇)
【HenCoder Android 开发进阶】自定义 View 1-7:属性动画(进阶篇)
一,概述:
1.1,动画可以分为两类:Animation 和 Transition
1.2,Animation 又可以再分为 View Animation 和 Property Animation 两类:
1.3,View Animation 是纯粹基于 framework 的绘制转变,比较简单,如果你有兴趣的话可以上网搜一下它的用法;
1.4,Property Animation,属性动画,这是在 Android 3.0 开始引入的新的动画形式,不过说它新只是相对的,它已经有好几年的历史了,而且现在的项目中的动画 99% 都是用的它,极少再用到 View Animation 了。属性动画不仅可以使用自带的 API 来实现最常用的动画,而且通过自定义 View 的方式来做出定制化的动画。除了这两种 Animation,
2,还有一类动画就是 Transition。 Transition 这个词的本意是转换,在 Android 里指的是切换界面时的动画效果,
二,帧动画,View动画和属性动画(也叫补间动画,Propety Animation)的区别:
- 1,帧动画,比如动画片就是用帧动画来制作的,将许多图片一帧一帧的播放,给我们呈现出一种假象,感觉它在播放.
- 2,补间动画和属性动画(android3.0出来的)都可以用来制作旋转,平移,缩放等动画,
但补间动画和属性的动画的区别在于:
属性动画可以修改动画的属性值:比如属性动画从A点平移到B点,那么点击B点才会弹吐司;而补间动画,从A点平移到B点,点击A点才会弹吐司,它的功能仍然留在A点,没有改变.
三,常见的插值器:
1,什么是插值器:能够改变动画的执行速度
2,常见的插值器:AccelerateInterpolator(加速),DecelerateInterpolator(减速),LinearInterpolator(匀速),AccelerateDecelerateInterpolator(先加速再减速),BounceInterpolator(反弹数次后停止)
四,属性动画,
1,工作原理:在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果.
2,主要的类ValueAnimator
,ObjectAnimator
2.1,ValueAnimator:这个动画是针对属性的值进行动画的 ,不会对UI造成改变,不能直接实现动画效果。需要通过对动画的监听去做一些操作,在监听中将这个值设置给对应的属性,对应的属性才会改变。
2.2,ObjectAnimator:直接动画所给的对象,他会调用对象对应属性的get/set方法吧属性的值设置给对象的属性,直接实现动画效果。
2.3,
ValueAnimator
类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接 对对象属性进行操作;
2.4,
ObjectAnimator
类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接 对对象属性进行操作;
3.属性动画:第一种实现方式
1,布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/freecolor_white"
android:fitsSystemWindows="true">
<ImageView
android:id="@+id/iv_splash"
android:scaleX="1.5"
android:scaleY="1.5"
android:alpha="0.5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/splash_sheep_newyear"/>
</LinearLayout>
2,代码
ViewCompat.animate(iv_splash)
.scaleX(1.0f).scaleY(1.0f)
.alpha(1.0f).setDuration(2000)
.setListener(new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
}
@Override
public void onAnimationEnd(View view) {
startAt(LoginActivity.class);
finish();
}
@Override
public void onAnimationCancel(View view) {
}
});
4.属性动画:第二种实现方式
4.1,ObjectAnimator,代码实现
//属性动画-平移
public void translate(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationY", 0, 100);
animator.setDuration(1000);//时长
animator.start();//播放动画
}
//旋转
public void rotate(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotation", 0, 360);//以z轴为参考系旋转
animator.setDuration(1000);
animator.start();
}
//缩放
public void scale(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "scaleX", 0, 3);//缩放
animator.setDuration(1000);
animator.start();
}
//透明
public void alpha(View view){
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 1, 0);//透明度
animator.setDuration(1000);
animator.start();
}
//动画集合
public void set(View view){
//1.x轴平移动画
ObjectAnimator xAnimator = ObjectAnimator.ofFloat(view, "translationX", 0, 100);
//2.y轴平移动画
ObjectAnimator yAnimator = ObjectAnimator.ofFloat(view, "translationY", 0, 100);
ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", 0, 360);//以z轴为参考系旋转
//创建属性动画集合
AnimatorSet set = new AnimatorSet();
//set.playTogether(xAnimator, yAnimator);//一起播放
//同时执行2个平移动画,再执行旋转动画
set.play(xAnimator).with(yAnimator).before(rotation);
set.setDuration(1000);
set.start();
}
4.2,xml实现动画
在res下新建animator文件夹,在animator新建xml文件
android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart
android:repeatCount = “0” // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
android:startOffset ="1000" // 动画延迟开始时间(ms)
android:valueType="intType" // 变化值类型 :floatType & intType
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:valueFrom="0"
android:valueTo="360"
android:propertyName="rotation"
android:repeatCount="infinite"
android:repeatMode="reverse"/>
public void xml(View view){
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.set_animation);
animator.setTarget(view);
animator.start();
}
五,View动画
//5.1-,平移动画
public void translate() {
TranslateAnimation translate = new TranslateAnimation(0, 100, 0, 0);
translate.setDuration(1000);
translate.setRepeatCount(TranslateAnimation.INFINITE);// 循环播放
translate.setRepeatMode(TranslateAnimation.REVERSE);
iv.startAnimation(translate);// 开始播放
}
//5.2,缩放
public void scale() {
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2);
scale.setDuration(1000);
scale.setRepeatCount(ScaleAnimation.INFINITE);// 循环播放
scale.setRepeatMode(ScaleAnimation.REVERSE);
iv.startAnimation(scale);// 开始播放
}
// 5.3,旋转
public void rotate() {
RotateAnimation rotate = new RotateAnimation(0, 360, iv.getWidth() / 2,
iv.getHeight() / 2);
rotate.setDuration(1000);
rotate.setRepeatCount(RotateAnimation.INFINITE);// 循环播放
rotate.setRepeatMode(RotateAnimation.REVERSE);
iv.startAnimation(rotate);// 开始播放
}
// 5.4,透明
public void alpha() {
AlphaAnimation alpha = new AlphaAnimation(1, 0);// 从不透明到透明
alpha.setDuration(1000);
alpha.setRepeatCount(AlphaAnimation.INFINITE);// 循环播放
alpha.setRepeatMode(AlphaAnimation.REVERSE);
iv.startAnimation(alpha);// 开始播放
}
// 5.5,集合
public void set() {
AnimationSet set = new AnimationSet(true);
TranslateAnimation translate = new TranslateAnimation(0, 100, 0, 0);
ScaleAnimation scale = new ScaleAnimation(0, 2, 0, 2);
set.setDuration(1000);
set.setRepeatCount(AnimationSet.INFINITE);// 循环播放
set.setRepeatMode(AnimationSet.REVERSE);
set.addAnimation(translate);
set.addAnimation(scale);
iv.startAnimation(set);// 开始播放
}
5.7View动画的xml实现
在res文件夹下新建anim文件夹.
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXDelta="0"
android:toXDelta="100%p"
android:repeatCount="infinite"
android:repeatMode="reverse"/>
六,Activity的跳转动画
1,overridePendingTransition方法,这个方法必须放在startActivity()和finish()后面。
2, 它只在android2.0以及以上版本上适用
3,当我们不想要Activity到另一个Activity的过度动画时候可以设置为overridePendingTransition(0,0)
这样切换Activity时 就没有过度动画了。
4,overridePendingTransition 需要在主线程中调用才会有效果. 如果是在子线程中调用将会没有效果
5.进入和退出的动画时间必须要相等,不然会无效,如果第一个时间慢,第二个快,就会出现第二个界面黑屏,第一个开始动画效果,那是因为第二个已经在时间内完成了动画,切记。
这种应该很少出现吧,
6,TabHost中的Activity调用overridePendingTransition()方法无效
查看这个博客:TabHost中的Activity调用overridePendingTransition()方法无效
7,旧的Activity(exit,右边的动画)实际上是x轴坐标发生了变化:0—>-100%p
新的Activity(enter,左边的动画)实际上是x轴坐标发生了变化:100%p—>0
//overridePendingTransition方法,这个方法必须放在startActivity()和finish()后面。
Intent intent = new Intent(this,XXXXX.class);
startActivity(intent);
overridePendingTransition(R.anim.enter,R.anim.exit);
//当Activity退出时
@Override
public void finish(){
super.finish();
overridePendingTransition(R.anim.enter,R.anim.exit);
}
进入的动画,也就是新的activity
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p"
android:duration="600"
android:toXDelta="0"
/>
</set>
退出的动画,也就是旧的activity
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0"
android:duration="600"
android:toXDelta="-100%p"
/>
</set>