第七章
1. 视图动画(View 动画)
- Animation 框架定义了透明度AlphaAnimation, 旋转RotateAnimation, 缩放ScaleAnimation和位移TranslateAnimation几种常见的动画。
- 控制的是整个View, 实现原理是每次绘制视图时View所在的ViewGroup中的drawChild方法获取该View的Animation的Transformation值,然后调用canvas.concat(transformationToApply.getMatrix()),通过矩阵运算完成动画帧。如果动画没有完成,就继续调用invalidate方法,启动下次绘制来驱动动画,从而完成整个动画的绘制。
- 视图动画的问题在于当View 发生变化后,响应时间还停留在之前的位置
- AnimationSet 动画集合
- AnimationListener 设置动画的监听回调方法
2.属性动画
3.0 之后新增了属性动画(Animator框架),使用的最多的是AnimatorSet 和 ObjectAnimator 配合
,使用ObjectAnimator进行更精细化的控制,只控制一个对象的一个属性,而使用多个ObjectAnimator组合到AnumatorSet 形成一个动画。而且ObjectAnimator 能够自动驱动,调用setFragmeDely(longframeDelay) 设置动画帧之间的间隙,在不影响动画效果的情况下减少CPU 资源消耗ObjectAnimator
- 创建通过静态工厂类直接返回一个ObjectAnimator 对象,参数包括一个对象和对象的属性名字,但这个属性必须有get 和 set 方法,内部会通过Java 反射调用set 函数修改对象属性值。同样也可以调用 setInterpolator 设置相应的插值器。常用的可以直接使用的属性动画的属性包括以下:
- translationX和translationY:控制view从它布局容器左上角坐标偏移的位置;
- rotation、rotationX和rotationY:控制view围绕支点进行2D和3D旋转;
- scaleX和scaleY:控制view围绕着它的支点进行2D缩放;
- pivotX和pivotY:控制支点位置,围绕这个支点进行旋转和缩放处理。默认情况下,支点是view的中心点;
- x和y:控制view在它的容器中的最终位置,它是最初的左上角坐标和translationX、translationY的累计和;
- alpha:控制透明度,默认是1(不透明)
如果一个属性没有get,set方法,可以自顶一个一个Wrapper类,简介的给属性提供get/ set方法
private static class WrapperView {
private View mTragetView;
public WrapperView(View traget) {
mTragetView = traget;
}
public int getWidth() {
return mTragetView.getLayoutParams().width;
}
public void setWidth(int width) {
mTragetView.getLayoutParams().width = width;
mTragetView.requestLayout();
}
}
// 调用方法
WrapperView wrapperView = new WrapperView(mButton);
ObjectAnimator animator = ObjectAnimator.ofFloat(wrapperView, "translationX", 300);
animator.setDuration(1000);
animator.start();
- PropertyValuesHolder
- 类似视图动画中的AnimationSet,在属性动画中,如果针对同一个对象的多个属性,要同时作用多种动画可以使用PropertyValuesHolder
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(mImageViews.get(0), pvh1, pvh2, pvh3).setDuration(1000).start();
ValueAnimator
- ValueAnimator 在属性中非常重要,ObjectAnimator 也是继承自它,它本身不提供任何动画效果,更像是数值发生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程。可以在ValueAnimator 的 AnimatorUpdateListener 中监听数值的变化, 从而完成动画的变换。
动画的监听
- 一个完整的动画有Start, Repeat , End , Cancel 四个过程,通过Android提供了接口,大部分时候我们只关注onAnimationEnd 事件,所有Android 也提供了一个AnimatorListenerAdapter来让我们选择必要的事件进行监听
// 向左移动200
ObjectAnimator animator4 = ObjectAnimator.ofFloat(mImageViews.get(4),
"translationX", -200F);
animator4.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator4.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
AnimatorSet
- 对一个属性同时作用多个属性动画效果,前面的PropertyValuesHolder 实现了这样的效果。而AnimatorSet 不仅能实现,爱能够实现更为精准的顺序控制。通过 playTogether, playSequentially, animSet.play(),with().before(),after() 这些方法控制多个动画的协同
在XML 中使用属性动画
- 这个属性动画必须建在animator 文件夹下(Animator),anim文件夹下不起作用(Animation)
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="2.0"
android:valueType="floatType">
</objectAnimator>
// 调用xml文件中的属地动画
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.scale_x);
animator.setTarget(mImageViews.get(0));
animator.start();
- 在Android 3.0 之后,View 增加了 animate 方法来直接驱动属性动画,可以理解为属性动画的简写方法
imageView.animate().alpha(0).y(100).setDuration(1000)
.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
- 布局动画
- 布局动画是指作用在ViewGroup 上,给ViewGroup 增加View 时添加一个动画过度效果。
- 最简单的是在ViewGroup 的xml 中新增 android:animateLayoutChanges=”true”,这样当ViewGroup 添加子View的时候,子View会呈现逐渐显示的过渡效果,这个是Android默认的效果切无法替换
- 可以通过LayoutAnimationController 类来自定义一个子View 的过度效果
- LayoutAnimationController 第一个参数是需要作用的动画,第二个参数是每个子View的delay事件。当delay事件不为0时,可以设置子View显示的顺序
- LayoutAnimationController.ORDER_NORMAL 顺序
- LayoutAnimationController.ORDER_RANDOM 随机
- LayoutAnimationController.ORDER_REVERSE 反序
// 设置子View 的过度动画效果
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
// 设置过渡效果
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1);
sa.setDuration(2000);
// 设置布局动画的显示属性
LayoutAnimationController lac = new LayoutAnimationController(sa, 0.5F);
lac.setOrder(LayoutAnimationController.ORDER_NORMAL);
// 为ViewGroup 设置布局动画
- Interpolator (插值器)
- 这部分可参考文档, 常用的也没有几个插值
- 自定义动画
- 创建自定义动画,只需要实现它的applyTransformation 的逻辑就可以了,不过通常还需要覆盖父类的initialize方法来实现初始化工作。
- applyTransformation(float interpolatedTime,Transformation t) 第一个参数是插值器的时间因子,第二个是矩阵的封装类 一般用这个类获得当前的矩阵对象
SVG 动画
Android 在 5.x之后增加了对SVG适量图形的支持
先了解一下什么是SVG:
可伸缩矢量图形(Scaleable Vector Graphics)
定义用于网格的机遇矢量的图形
使用XML 格式定义图形
图像在放大或改变尺寸的情形下其图形质量不会有所损失
万维网联盟的标准
与DOM 和 XSL 之类的 W3C 标准是一个整体
使用
标签创建SVG,就像用指令控制一只画笔,例如移动画笔到某一坐标,画一条线,画一条曲线等。 标签所支持的指定有以下几种: - M = moveto(M X,Y) ; 将画笔移动到指定的坐标位置,未发生绘制
- L = lineto(L X,Y); 画直线到指定的坐标位置
- H = horizontal lineto(H X) ; 画水平线到指定的X坐标位置
- V = vertical lineto(V Y); 画垂直线到指定的Y坐标
- C = curveto(C X1, Y1, X2, Y2, ENDX, ENDY) ; 三次贝塞尔曲线
- S = smooth curveto(S, X2, Y2, ENDX, ENDY) 三次贝塞尔曲线
- Q = quadratic Belzier curve(Q X,Y, ENDX, ENDY) 二次贝塞尔曲线
- T = smooth quadratic Belzier curveto(T ENDX, ENDY) 映射前面路径后的终点
- A = elliptical Arc(A, RX, RY, XROTATION, FLAG1, FLAG2, X, Y) 弧线
- Z = closepath(); 关闭路径
注意事项
- 坐标轴以(0,0) 为中心,x轴向右,y轴向下
- 所有指令大小写均可,大写绝对定位,参照全局坐标系,小写相对定位,操作父容器坐标系
- 指令和数据间的空格可以省略
- 同一指令出现多次可以只用一个
SVG 参数的写法固定且复杂,完全可以使用程序实现,所以一般通过SVG 编辑器来编辑SVG 图形。
书中给出了一个编辑的网站Android 中使用SVG
- Google 在 5.x 后提供了两个新的API 来帮助支持SVG :VectorDrawable, AnimatedVerctorDrawable。其中 VectorDrawable 让你可以创建基于XML 的SVG 图形,并结合AnimatedVectorDrawable 来实现动画效果.具体的实现效果可以参考demo
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!