以下的内容是我看《android开发艺术探索》 的一个记录 只是方便以后使用查阅
LayoutAnimation
layouyAnimation 用于ViewGroup 为 ViewGroup 指定一个动画,这样当子元素出场的时候会具有这种动画效果
下面的代码是layouyAnimation 用于ListView 的一个例子,效果是:每一个Item 是从右面飞入的
1.现定义item的动画效果
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator="true" >
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0" />
<translate
android:fromXDelta="500"
android:toXDelta="0" />
</set>
android:interpolator 是 插值器,插入期空值动画的速度 如果不指定就会使用默认的 插值器
android:shareInterpolator="true" 表示集合中的动画是否和集合共享同一个插值器,如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认的@android:anim/accelerate_interpolator 加速减速插值器
2.定义LayoutAnimation
anim/anim_layout"
<layoutAnimation
xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="reverse"
android:animation="@anim/anim_item"/>
android:delay 表示子元素开始动画的时间延迟,如果子元素入场动画的时间周期是300ms,那么0.5表示每个子元素都会延迟150ms才会播放入场动画,总体来说,第一个子元素延迟150ms 开始播放入场动画,第二个子元素延迟300ms开始播放入场动画,依此类推
android:animationOrder 表示子元素动画的顺序 ,有三种选项 :normal 、reverse 和 random
normal:按顺序播放入场动画
reverse:逆向播放入场动画
random:随机播放入场动画
3.为ViewGroup 指定 android:layoutAnimation="@anim/anim_layout" 这样每一个Item都会具有出场动画了
<ListView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/anim_layout"
android:background="#fff4f7f9"
android:cacheColorHint="#00000000"
android:divider="#dddbdb"
android:dividerHeight="1.0px"
android:listSelector="@android:color/transparent" />
以上的代码就是在xml 中设置 layoutAnimation 的基本步骤,下面介绍的是在java 代码中实现
Animation animation = AnimationUtils.loadAnimation(DemoActivity_2.this,R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);
Activity的切换效果
在startActivity(Intent)和finish()调用 overridePendingTransition(R.anim.enter_anim,R.anim.exit_anim); 就可以实现Activity的切换效果
下面是属性动画的使用
下面的代码是使用属性动画的一个例子:
//沿着Y轴方向平移一段距离
private void translation(View target)
{
ObjectAnimator.ofFloat(target,"translationY",-target.getHeight()).start();
}
//改变背景颜色
private void changeBackground(View target)
{
ValueAnimator colorAnim = ObjectAnimator.ofInt(target,"backgroundColor",/*Red*/0xFFFF8080,/*Blue*/0xFF8080FF);
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
}
//动画集合,5秒对View 的旋转,平移,缩放和透明度都进行改变
private void useSet(View view)
{
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(view, "rotationX", 0, 360),
ObjectAnimator.ofFloat(view, "rotationY", 0, 180),
ObjectAnimator.ofFloat(view,"rotation", 0, -90),
ObjectAnimator.ofFloat(view,"translationX", 0, 90),
ObjectAnimator.ofFloat(view,"translationY", 0, 90),
ObjectAnimator.ofFloat(view, "scaleX", 1, 1.5f),
ObjectAnimator.ofFloat(view, "scaleY", 1, 0.5f),
ObjectAnimator.ofFloat(view, "alpha", 1, 0.25f, 1)
);
set.setDuration(5 * 1000).start();
}
上面的代码是用JAVA实现的,属性动画也可以使用XML实现,用XML实现不能动态改变数字所以推荐使用JAVA代码实现
ObjectAnimator 继承自 ValueAnimator
在用AnimatorSet的时候 set.playTogether 是动画集的子动画一起播放的意思,其实还有set.playSequentially(),set.playSequentially()表示集合中的子动画按照前后顺序依次播放
ObjectAnimator.ofFloat(target,"translationY",-target.getHeight()).start();
target:改变的对象
"translationY":属性动画的操作的属性的名称,然后改变其值来实现动画,如果没有属性名或者属性名不正确那么属性动画就不能正确的执行,还有一种可能会导致动画不能正确执行,在属性对应的get 和 set不存在或者不能改变属性,这种情况下也不能执行,下面会写到的
target.getHeight():其实这里可以写很多一个对应的数组,数组就是动画执行后要设置的值,比如上面的代码是ofFloat 那么填写的float 数组
ObjectAnimator 继承自 ValueAnimator 所以ValueAnimator 的设置同样可以在ObjectAnimator 中使用
colorAnim.setDuration(3000);//设置执行的时间
colorAnim.setEvaluator(new ArgbEvaluator());//估值器 ,系统提供了三个估值器: IntEvaluator(针对整型属性)、FloatEvaluator(针对浮点型属性)、ArgbEvaluator(针对Color 属性)
colorAnim.setRepeatCount(ValueAnimator.INFINITE);//动画重复的次数
colorAnim.setRepeatMode(ValueAnimator.REVERSE);//动画的重复模式
可以用.setStartDelay() 设置延迟时间
有些的属性不能通过set 和 get 正确设置:有三种方法可以解决
1.给对象加上get和set方法,如果你有权限
2.用一个类来包装,间接为其提供get 和 set 方法
下面的代码就是例子
//用一个类来包装原始对象,间接为其提供get和set方法
private void performAnimation()
{
ViewWrapper wrapper = new ViewWrapper(button1);
ObjectAnimator.ofInt(wrapper,"width",500).setDuration(5000).start();
}
private static class ViewWrapper
{
private View mTarget;
public ViewWrapper(View target)
{
mTarget = target;
}
public int getWidth()
{
return mTarget.getLayoutParams().width;
}
public void setWidth(int width)
{
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
上面用的是button 做的例子 应为button 的 setWidth 不能改变button 的宽度
3.才用ValueAnimator,监听动画过程,自己实现属性的改变
private void valuePerformAnimation(final View target, final int start, final int end)
{
ValueAnimator valueAnimator = ValueAnimator.ofInt(1,100);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
//持有一个IntEvaluator 对象,方便下面估值的时候使用
private IntEvaluator mIntEvaluator = new IntEvaluator();
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获得当前动画的进度值,整形,1~100之间
int currentValue = (int) animation.getAnimatedValue();
//获得当前精度占整个动画过程的比例,浮点型,0~1
float fraction = animation.getAnimatedFraction();
//直接调用整数型估值器,通过比例计算出宽度,然后在设给Button
target.getLayoutParams().width = mIntEvaluator.evaluate(fraction,start,end);
target.requestLayout();
}
});
valueAnimator.setDuration(5000).start();
}