Android26-动画机制与使用技巧
Android View动画
Animation 框架定义了透明度、旋转、缩放和位移几种常见的动画,而且控制的是整个View。
- 以下是一些常用动画的设置
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void btnAlpha(View view) {
AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(3000);
view.startAnimation(aa);
}
public void btnRotate(View view) {
//0 :旋转起始角度
//360 : 旋转终止角度
//0,0 :绕那个点旋转
RotateAnimation ra = new RotateAnimation(0, 270, 0, 0);
ra.setDuration(3000);
view.startAnimation(ra);
}
public void btnRotateSelf(View view) {
RotateAnimation ra = new RotateAnimation(0, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ra.setDuration(3000);
view.startAnimation(ra);
}
public void btnTranslate(View view) {
//0 : x起始位置
//200 :x结束位置
//0 : y起始位置
//300 :y结束位置
TranslateAnimation ta = new TranslateAnimation(0, 200, 0, 300);
ta.setDuration(3000);
view.startAnimation(ta);
}
public void btnScale(View view) {
//1 : x起始大小
//1 : x结束大小
//0 : y起始大小
//2 : y结束大小
ScaleAnimation sa = new ScaleAnimation(1, 1, 0, 2);
sa.setDuration(3000);
view.startAnimation(sa);
}
public void btnScaleSelf(View view) {
ScaleAnimation sa = new ScaleAnimation(0, 1, 0, 1,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
sa.setDuration(3000);
view.startAnimation(sa);
}
public void btnSet(View view) {
//动画组
AnimationSet as = new AnimationSet(true);
as.setDuration(3000);
//透明度动画
AlphaAnimation aa = new AlphaAnimation(0, 1);
aa.setDuration(3000);
as.addAnimation(aa);
//平移动画
TranslateAnimation ta = new TranslateAnimation(0, 100, 0, 200);
ta.setDuration(3000);
as.addAnimation(ta);
//启动动画
view.startAnimation(as);
}
}
Android属性动画
由于Animation框架改变的只是显示效果,并不能相应事件, 因此,在Android3.0之后引入了属性动画框架(Animator);Animator框架中使用最多的是AnimatorSet和ObjectAnimator的配合。
- ObjectAnimator
ObjectAnimator是属性动画框架中的最重要的实行类,创建一个ObjectAnimator只需通过他的静态工厂类直接返回一个ObjectAnimator对象,参数包括一个对象和对象的属性,但属性必须有get和set函数。
ObjectAnimator animator = ObjectAnimator.ofFloat( view, "translationX", 300); animator.setDuration(300); animator.start();
ObjectAnimator : 常用动画属性说明
- translationX 和 translationY :这两个属性通常用来控制view的平移。
- rotaion、rotationX、rotationY :这三个属性控制view对象围绕支点进行2D和3D旋转。
- scaleX 和 scaleY :这两个属性控制view对象围绕它的支点进行2D缩放。
- pivotX 和 privotY :这两个属性控制view对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点位置就是view对象的中心点。
- x 和 y :这两个属性描述了view对象在它的容器中的最终位置,它是最初的做坐标和tranlationX 和 translationY值的累计和。
- alpha : 表示view对象的alpha透明度,默认值是1(不透明),0代表完全透明(不可见)。
注:如果一个属性没有get、set方法,也通过包装类的方法给属性增加get、set方法来实现动画,代码如下:
> private static class WrapperView {
private View mTarget;
public WrapperView(View target) {
mTarget = target;
}
public int getWidth() {
return mTarget.getLayoutParams().width;
}
public void setWidth(int width) {
mTarget.getLayoutParams().width = width;
mTarget.requestLayout();
}
}
通过以上代码,就给属性提供了set、get方法,使用时只需要操作包装类即可
> WrapperView wrapper = new WrapperView(view);
ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(3000).start();
- PropertyValuesHolder
类似视图动画的AnimationSet,属性动画如果对同个对象要定义多个属性,就要用刀PropertyValuesHolder来实现。
> //同时操作多个属性动画
PropertyValuesHolder pvh1 = PropertyValuesHolder.ofFloat("translationX", 300f);
PropertyValuesHolder pvh2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvh3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvh1, pvh2, pvh3).setDuration(3000).start();
- ValueAnimator
ValueAnimator在属性动画中占有非常重要的地位,他本身不提供任何动画效果,他更像一个数值产生器,用来产生具有一定规律的数字,从而让调用者来控制动画的实现过程。
> //ValueAnimator
ValueAnimator animator = ValueAnimator.ofFloat(0, 400);
animator.setTarget(view);
animator.setDuration(1000).start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Float value = (Float) animation.getAnimatedValue();
//TODO use the value
if (value < 200) {
ObjectAnimator.ofFloat(view, "translationX", 200).setDuration(1000).start();
} else {
ObjectAnimator.ofFloat(view, "translationY", 200).setDuration(1000).start();
}
}
});
- 动画事件的监听
一个完整的动画具有Start、Repeat、End、Cancel四个过程,通过Android提供的API可以很方便的监听这四个事件
> ObjectAnimator animator = ObjectAnimator.ofFloat(view, "alpha", 0.5f);
animator.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) {
//动画重复时
}
});
- AnimatorSet
对于一个对象同时作用多个属性动画,可以用PropertyValuesHolder实现,同样也可以用AnimatorSet实现,而且AnimatorSet同时也能实现更为精确的顺序控制。
>//使用AnimatorSet实现作用多个动画
ObjectAnimator animator1 = ObjectAnimator.ofFloat(view, "translationX", 300f);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0f, 1f);
ObjectAnimator animator3 = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0f, 1f);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(animator1, animator2, animator3);
set.start();
AnimatorSet正是通过playTogether()、playSequentially()、animSet.play().with()、before、after()等方法来对多个动画的播放顺序做精确的控制的。
- View的animate方法
在Android3.0之后,google给view增加了animate方法来直接设置属性动画。代码如下
>//通过view的animate方法直接设置属性动画
view.animate().alpha(0).y(300).setDuration(3000).withStartAction(new Runnable() {
@Override
public void run() {
//动画开始时
}
}).withEndAction(new Runnable() {
@Override
public void run() {
//动画结束时
}
}).start();
}
Android布局动画
布局动画,是指作用在ViewGroup上的动画,当ViewGroup增加view时添加一个动画的过渡效果。
最简单的布局动画是在ViewGroup的XML中,使用以下代码来设置android:animateLayoutChanges="true"
另外还可通过LayoutAnimationController类来自定义一个子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设置布局动画 ll.setLayoutAnimation(lac);
LayoutAnimationController的第一个参数是需要作用的动画,第二个参数是每个子view的显示时间,当delay时间不为0时可以设置子view显示的顺序
- LayoutAnimationController.ORDER_NORMAL--正序
- LayoutAnimationController.ORDER_RANDOM -- 随机
- LayoutAnimationController.ORDER_REVERSE -- 反序
- Interpolators(插值器)
通过插值器,可以定义动画变换的速率,有点类似于物理中的加速度。主要作用是用来控制目标变量的变化值然后进行对应的操作。
自定义动画
创建自定义动画,通常情况下只需要覆盖父类的initialize方法来实现一些初始化工作,并且实现applyTransformation逻辑就可以了。
> public
class
CustomAnim extends Animation
{
private int mCenterWidth;
private int mCenterHeight;
private Camera mCamera = new Camera();
private float mRotateY = 0.0f;
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
//设置默认时长
setDuration(2000);
//设置动画结束后保留状态
setFillAfter(true);
//设置默认插值器
setInterpolator(new BounceInterpolator());
mCenterHeight = height/2;
mCenterWidth = width/2;
}
//暴漏一个接口给外界设置旋转角度
public void setRotateY(float rotateY) {
mRotateY = rotateY;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
//获得当前的矩阵对象
final Matrix matrix = t.getMatrix();
mCamera.save();
//使用Camera设置旋转的角度
mCamera.rotateY(mRotateY * interpolatedTime);
//将旋转变化作用到matrix上
mCamera.getMatrix(matrix);
mCamera.restore();
//通过pre方法设置矩阵作用前的偏移量来改变旋转中心
matrix.preTranslate(mCenterWidth, mCenterHeight);
matrix.postTranslate(-mCenterWidth, -mCenterHeight);
}
}
在上面这个例子中用到了Camera,这里的Camera不是指手机中的相机,而是android.graphics.Camera中的Camera类,它封装了openGL的3D动画,从而可以非常方便的创建3D动画效果。使用的时候就是通过设置三个坐标轴(X、y、z)的旋转角度,从而实现3d动画的效果
>mCamera.save();
//使用Camera设置旋转的角度
mCamera.rotateY(mRotateY * interpolatedTime);
mCamera.rotateY(mRotateY * interpolatedTime);
mCamera.rotateZ(mRotateY * interpolatedTime);
//将旋转变化作用到matrix上
mCamera.getMatrix(matrix);
mCamera.restore();
SVG矢量动画
SVG : 可伸缩适量图形,于Bitmap(位图)相比,最明显的优点是放大不会失真。
-
<path>
标签
使用
<path>
标签创建SVG,就像用指令的方式来控制一只画笔,例如移动画笔到某一坐标位置,画一条直线,画一条曲线等。常用<path>
指令有以下几种:
- 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 = quadraic Belzier curve(Q X, Y, ENDX, ENDY) : 二次贝塞尔曲线。
- T = smooth quadratic Belzier curveto(T ENDX, ENDY) : 映射前面路径后的终点。
- A = cliptical Arc(A RX, RY, XROTATION, FLAG1, FLAG2, x, y) : 弧线。
- Z = closepath() : 关闭路径。
注:使用这些指令需注意以下几点
- 坐标轴以(0, 0) 为中心,X轴水平向右, Y轴水平向下。
- 所有指令大小写均可,大写表示绝对定位,参照全局坐标系;小写相对定位,参照父容器坐标系。
- 指令和数据间的空格可以省略。
- 同一指令出现多次可以只用一个。
- Android中使用SVG
Goggle在Android5.x中提供了VectorDrawable和AnimatedVectorDrawable两个API来帮助支持SVG,首先使用VectorDrawable来创建基于XML的SVG图形,再结合AnimatedVectorDrawable来实现动画效果。