android自定义animation

1、什么是自定义animation

在android中,系统提供了一些可以直接使用的animation,如TranslateAniamtion、ScaleAnimation、AlphaAnimation及RotateAnimation。这四种动画对应着平移、缩放、渐变及旋转动画。 在开发中,我们只需要定义好animtion对象,便可以在view上调用startAnimation来实现view的动画。
但如果有些动画,不能用这些动画实现该怎么办呢? 如一些曲线类型的动画。
那么,我们可以通过自定义的animation来实现(通过属性动画也可以实现)。
通过查看上面四种动画的源码可以发现,它们均是继承了Animation类。
该类的说明如下:

/**
 * Abstraction for an Animation that can be applied to Views, Surfaces, or
 * other objects. See the {@link android.view.animation animation package
 * description file}.
 */
public abstract class Animation implements Cloneable {

所以我们也可以尝试继承该类,通过覆写相关方法来实现自定义动画。

2、Rotate3DAnimation实例分析

在google提供的apidemo工程中,有一个Rotate3DAnimation类,从名字可以知道是使view产生3D效果的动画。 其中覆写了Animation类的两个重要方法, 代码如下:

@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
    super.initialize(width, height, parentWidth, parentHeight);
    mCamera = new Camera();
}

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    final float fromDegrees = mFromDegrees;
    float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);

    final float centerX = mCenterX;
    final float centerY = mCenterY;
    final Camera camera = mCamera;

    final Matrix matrix = t.getMatrix();

    camera.save();
    if (mReverse) {
        camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
    } else {
        camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
    }
    camera.rotateY(degrees);
    // 将camera的变化矩阵存入matrix,而matrix会填入Transformation中去,最后系统会调用这个matrix
    camera.getMatrix(matrix);
    camera.restore();
	
	// pre 的含义是 原有矩阵在前,现有运算矩阵放在原矩阵后面。 
    matrix.preTranslate(-centerX, -centerY);
    // 同理,post的含义是 原有矩阵在在后,现有运算矩阵在前。  故这两行代码的含义在矩阵的最前面 平移 centerX
    // 与 centerY ,在最后面 平移 - centerX 与 -centerY。 所以这两行代码交换先后也没关系。 
    matrix.postTranslate(centerX, centerY);
}

其中,initialize方法中传入了当前做动画的view的宽高和当前view的父view的宽高,在这里可以根据需要来做一些初始化的操作。
applyTransformation方法在动画期间会持续回调,interpolatedTime是当前动画的进度,取值为[0-1], Transformation则封装了动画相关的参数。 此例中将 camera 的matrix 设置给 Transformation 实现在某个特定时间的变化。

3、Camera相关知识点

这个camera是 android.graphics 包下的类,而不是指相机硬件。 这个camera相当于是屏幕外的一个眼睛,通过改变这个“眼睛”的角度及方位等,我们就可以看到不同的视图(也即在屏幕上显示不同的图像)。

由于camera涉及3D操作,所以我们有必要先弄清楚camera下的坐标系。 camera视角下的坐标系与普通的屏幕坐标系不同。
在camera视角下,每个view的左上角为坐标原点(即每个view只要左上角的位置不同,那么camera的坐标原点也不同,可以想像成每个view都有一个单独的camera,通过这个camera将物体映射在屏幕上)。

在camera坐标系中,x轴正向为屏幕向右,y轴正向为屏幕向上,z轴正向为垂直屏幕向外(面对屏幕时,朝向自已为正轴)
camera的位置就位于z轴 - 576 像素处(在z轴负半轴的 8 个单位处,每个单位是72像素)。

3.1 Camera常见操作

camera提供了平移、旋转的操作。 可以直接使用系统相关方法。 对于缩放,没有函数直接支持,但是可以通过平移或修改camera的位置来实现。

在使用旋转操作时,需要注意的是旋转的正负方向。
如果绕 x 轴旋转的话,正向为 屏幕里向屏幕外的方向(面对手机,朝自已的方向为正向)
如果绕 y 轴旋转的话,正向为 屏幕里向屏幕外的方向(面对手机,朝自已的方向为正向),同 x 轴。
如果绕 z 轴旋转的话,正向为顺时针方向。

弄清楚了旋转的方向,才能更好的设置旋转的角度,动画才会按照预想的运行。

除了平移操作,系统提供了设置camera位置的方法,签名如下:

/**
 * Sets the location of the camera. The default location is set at
 * 0, 0, -8.
 * 
 * @param x The x location of the camera
 * @param y The y location of the camera
 * @param z The z location of the camera
 */
public native void setLocation(float x, float y, float z);

从注释上可以看到,默认值为-8。 这里的 -8 相当于是负方向的8个单位。一个单位是72像素。 故上面说相机的位置在z轴-576像素处。

通过操作camera,就可以形成不同的视图效果。 但是如何将这种视图效果显示出来? camera提供了两种方法,如下:

1、mCamera.getMatrix(matrix);

2、mCamera.applyToCanvas(canvas);

在Rotate3DAnimation中使用的是方法1,由于其没有canvas,故将变化的matrix取出,然后按照matrix做动画。 在其他自定义view中则可以尝试使用方法2来实现相关效果。

4、Matrix相关知识点

在操作matrix时一定要搞清楚pre与post的区别。 之前老是记错,一段时间不用就理解反了。 这里正解的记法是,pre是将原矩阵放在前,pre操作的参数矩阵在后。而post正好相反,post是将原矩阵放在后,post操作的参数矩阵在前。

matrix类除了提供了常见的操作,如平移、旋转、缩放外还提供了一些较高级的用法。
1、错切。
2、setSinCos 主要用于旋转,相当于设置矩阵中的旋转位置的值。
3、mapPoints(float[] pts), 将输入的点按照当前矩阵进行变化,并将结果存入参数中。
4、setPolyToPoly()方法,参数中通过数组定义了两个多边形,该方法是计算从一个多边形变成另一个多边形所需的矩阵。
其他的方法较多,可以参考文档,这里仅列举一下常用的函数。以备平时开发查阅。

5、自定义animation实例

有了上面的基础知识后,便可以自定义一个动画出来。 这里尝试自定义一个抛物线动画。 关键代码如下:

@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
    super.initialize(width, height, parentWidth, parentHeight);
    mCamera = new Camera();

    mCenterX = width >> 1;
    mCenterY = height >> 1;
}

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    super.applyTransformation(interpolatedTime, t);

    // x 方向上匀速
    float x = X_DIS * interpolatedTime;
    // y 方向上加速, 为了动画效果,在y上乘以10000
    float y = 1.f / 2 * interpolatedTime * interpolatedTime * 10000;

    Matrix m = t.getMatrix();
    mCamera.save();
    // 注意方向,y轴向上是正方向。
    mCamera.translate(x, -y, 0);
    mCamera.getMatrix(m);
    mCamera.restore();

    m.preTranslate(-mCenterX, -mCenterY);
    m.postTranslate(mCenterX, mCenterY);
}

上面的抛物线没有经过精细的计算,只是为了动画效果随意设置的参数值。 从这个实例可以引申思考一下,对于一些非常规的动画可以尝试使用自定义动画来实现, 如各种曲线类型的动画等。

6、总结

1、自定义动画同普通的视图动画一样,只需在动画时传入动画对象即可。
2、使用Camera时注意其坐标系方向,该方向与view的方向有所区别。
3、matrix的pre操作与post操作均是相对于原矩阵而言的,pre即将原矩阵放在前操作,post亦然。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值