一:概述
这篇博客就将动画做一个总结。平时用用view动画基本能解决挺多问题。帧动画就时像播放电影一样一帧一帧的播放。属性动画就无敌了。直接更改某个属性来达到动画,其实他能更改的不只是view,任意对象都能更改,只要对应的属性有get,set方法。
1.view动画:
view动画就只有四种变化方式,平移,缩放,透明度,旋转。
我们先看看从xml文件中写 平移 动画
view动画的xml文件必须写在res/anim目录下。
android:fromXDelta 表示x起始值
android:toXDelta 表示x结束值
android:fromYDelta 表示y的起始值
android:toYDelta 表示y的结束值
android:duration 花多少时间将动画执行完毕
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXDelta="50.0"
android:toXDelta="200.0"
android:fromYDelta="0.0"
android:startOffset="1700"
android:toYDelta="100.0"
android:duration="1000"
/>
然后在java代码中用以下方式加载view动画。(其他view动画都是这种方式)
Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_translate);
translate.startAnimation(translateAnimation);
再来看看缩放动画
android:fromXScale=”1.0” 从最开始的样子,就是本来的样子,如果>1.0就是变大,<1.0就是变小
android:toXScale=”1.4” 就是从fromXScale变到toXScale的样子。从x方向上拉伸
android:interpolator 插值器,控制动画的变化速度
android:pivotX=”0%” 是从最左边开始变化,如果是10%就是从10%*自身的宽度的地方做分割点向两边变化
android:pivotY=”100%” 是从最下面开始变化,道理同android:pivotX
xml 文件写好后,就同上面写的Java代码中加载就行了。
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fromXScale="1.0"
android:toXScale="1.4"
android:fromYScale="1.0"
android:toYScale="0.6"
android:pivotX="0"
android:pivotY="1.0"
android:fillAfter="false"
android:duration="700" />
然后我们再来看看旋转动画。
fromDegrees开始旋转的角度
toDegrees旋转到的角度
startOffset是延迟多少秒开始执行动画
pivotX就是以哪个点开始旋转,如果pivotX ,pivotY都是50%的话,那么就是以中心开始旋转
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="-45"
android:pivotX="70%"
android:pivotY="50%"
android:startOffset="1700"
android:duration="400"
/>
来个比较简单的透明度的动画
android:fromAlpha开始的透明度
android:toAlpha最后的透明度
android:fillAfter动画运行到最后是否停留到最后的状态。true时停留到最后状态。
android:repeatCount 重复的次数
android:repeatMode=”restart” 重复的模式 restart 就是动画结束后又从头开始
android:repeatMode=”reverse” reverse就是动画结束后重结束的状态回到开始的状态,比如 从0旋转到了10然后就又从10返回旋转到了0,0又到10,如此往复。
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0"
android:toAlpha="1.0"
android:fillAfter="false"
android:duration="700"
android:repeatCount="5"
/>
还有将多个动画一起播放的。
< set >标签就是将动画放在一起然后一起播放。
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true" >
<translate
android:fromXDelta="0.0"
android:toXDelta="2000.0"
android:fromYDelta="0.0"
android:toYDelta="1000.0"
android:duration="1000"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
/>
</set>
再来看看直接在java代码中实现动画的编写。
缩放动画
ScaleAnimation 类对应的是缩放动画。
构造函数中所对应的参数从左到右分别是:
fromX 开始时x的值
toX 结束时x的值
fromY 开始时y的值
toY 结束时y的值
pivotX 缩放轴点的x坐标
pivotY 缩放轴点的y坐标
private void getscaleAnimationFromJava(){
// float fromX, float toX, float fromY, float toY,
// float pivotX, float pivotY
ScaleAnimation scaleAnimation = new ScaleAnimation(0.0f,2f,0f,2f,0.5f,0.5f);
scaleAnimation.setDuration(2000);
scale.startAnimation(scaleAnimation);
}
透明度动画:
这个就是花1s时间从完全透明变化到完全不透明
private void getAliphaAnimationFromJava() {
AlphaAnimation alipha = new AlphaAnimation(0.0f, 1.0f);
alipha.setDuration(1000);
alpha.startAnimation(alipha);
}
位移动画:
参数从左到右分别是
fromXType 开始时x坐标的类型(下面会讲部分类型的东西)
fromXValue 开始时x坐标的值
toXType 结束时x坐标的类型
toXValue 结束时x坐标的值
fromYType 开始时y坐标的类型
fromYValue 开始时y坐标的值
toYType 结束时y坐标的类型
toYValue 结束时y坐标值
private void getTranslateFromJava(){
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT,0f,
Animation.RELATIVE_TO_PARENT,0.5f,
Animation.RELATIVE_TO_PARENT,0f,
Animation.RELATIVE_TO_PARENT,0.5f
);
translateAnimation.setDuration(2000);
translate.startAnimation(translateAnimation);
}
旋转动画:
构造函数的参数从左到右分别是:
fromDegrees 开始旋转的角度
toDegrees 结束是旋转的角度
pivotXType 旋转点的x坐标的类型
pivotXValue 旋转点x坐标的值
pivotYType 旋转点的y坐标的类型
pivotYValue 旋转点y坐标的值
注:来看看坐标类型那个参数
Animation.ABSOLUTE 对应的值是绝对坐标 e.g 0.5对应的就是第0.5个px
Animation.RELATIVE_TO_SELF 相对与自身的值 e.g 0.5对应的就是第0.5 * 自身的值
Animation.RELATIVE_TO_PARENT 相对的是父控件的值 e.g 0.5对应的就是0.5 * 父控件的值
private void getRotateFromJava(){
// float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
// int pivotYType, float pivotYValue
// Animation.RELATIVE_TO_SELF 相对于自身0.5*自身的宽度就是中间,Animation.ABSOLUTE如果是0.5不再是中间,而是从左边开始的0.5个px。
RotateAnimation rotateAnimation = new RotateAnimation(0f,-100f,Animation.ABSOLUTE,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotateAnimation.setDuration(1000);
rotate.startAnimation(rotateAnimation);
}
ok view动画就差不多这些。一般的还是够用了。
2.LayoutAnimation
先看看图:
layoutAnimation是对viewgroup设置的动画。就是对容器设置的。但是动画是作用在容器的子元素上。
这个是每个子view做的动画
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:shareInterpolator="true" >
<translate
android:fromXDelta="0.0"
android:toXDelta="2000.0"
android:fromYDelta="0.0"
android:toYDelta="1000.0"
android:duration="1000"
/>
<rotate
android:fromDegrees="0"
android:toDegrees="-45"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
/>
</set>
android:delay 延迟多少秒
android:animation=”@anim/all_anim” 设置动画
android:animationOrder=”random” 动画执行顺序
android:delay=”30%” 设置每个子元素延迟多少执行,比如第一个延迟200ms进去的,那么第二个就是400ms开始执行。
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="30%"
android:animationOrder="random"
android:animation="@anim/all_anim" />
为listview设置动画。一般还是listview用的表较多
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layoutAnimation="@anim/layout_animaiton"
android:layout_height="match_parent" />
3.帧动画
这个文件写在drawable下
<?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/ic_launcher"
android:duration="200" />
<item
android:drawable="@drawable/cou"
android:duration="200" />
<item
android:drawable="@drawable/mingzi"
android:duration="200" />
</animation-list>
不要在oncreate方法中启动这个帧动画,因为还没有完全attach到window上,如果想已开启就开始这个动画。就在onWindowFocusChanged(boolean) 中调用。
public class DrawableAnimationActivity extends AppCompatActivity {
private AnimationDrawable rocketAnimation;
private ImageView img;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_drawable_animation);
img = (ImageView) findViewById(R.id.img);
img.setBackgroundResource(R.drawable.drawable_animation);
rocketAnimation = (AnimationDrawable) img.getBackground();
img.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
rocketAnimation.start();
}
});
}
}
4.属性动画:
我利用属性动画,做了一个波浪。(利用三角函数)
属性动画应该是无所不能的。
属性动画可以对任意对象的属性进行动画而不仅仅是view,动画默认时间间隔时300ms,默认帧率是10ms/s。效果是:在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。属性动画时在Android 3.0才开始有的。但是兼容以前的话可以利用nineoldandroids来兼容。但是nineoldandroids是view动画上建立的。所以本质还是view动画。
下面来看看这个波浪的实现细节吧。
因为这里面的曲线全是由200段直线组合成的。所以需要找到200个点。
这个波浪中只有一个波峰或者一个波谷,所以x方向上的坐标选了一个区间就是(offset,offset+PI)
这个区间被分成了200份,分别求出对应的y值,就做出了200个坐标,然后依次连接成线。然后再不断改变offset的值,然后invalide不断重绘就可以形成动画。
offset属性必须实现对应的get,set函数。
public int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
getPoint();
}
利用ObjectAnimator 将offset从0变道50用时10s
ObjectAnimator 是下面要讲到的ValueAnimator的子类。
private void objectJava(){
ObjectAnimator sin = ObjectAnimator.ofInt(sinView, "offset", 0, 50);
sin.setDuration(10000);
sin.start();
}
再看看利用来制作动画ValueAnimator,ValueAnimator这个不作用在某个对象上。
ValueAnimator.ofInt(0,10)。
value.setDuration(10000)
花时10s将值0变到10,但是没说把哪个对象的哪个值变化。
int currentValue = (Integer) animation.getAnimatedValue();
sinView.setOffset(currentValue);
在回调中自己调用
private void valueJava(){
ValueAnimator value = ValueAnimator.ofInt(0,10);
value.setDuration(10000);
value.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int currentValue = (Integer) animation.getAnimatedValue();
sinView.setOffset(currentValue);
}
});
value.start();
}
5.插值器
直接看看图吧。
参考书籍
《Android开发艺术探索》