Android launcher文件夹动效总结

这篇文档记录了一下自己在实际工作中实现的一些Android动画效果时的开发思路,总结了我自己如何看待Android动画问题,希望能给大家的动画开发提供一些思路和帮助。

一、Android动画基础

1.1 动画类型

  • Frame Animation:
    帧动画,顺序播放事先做好的图像,是一种画面转换动画
  • Tween Animation:
    补间动画(或者叫渐变动画),通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果
  • Property Animation:
    属性动画,通过动态地改变对象的属性从而达到动画效果,属性动画为API 11新特性

1.2 帧动画:

是指顺序执行预先设置好的一组图片,类似电影胶片的形式,设置每一帧drawable,在java代码中加载资源生成一个AnimationDrawable对象。例如:在xml中配置spin_animation.xml在文件夹res/drawable/中:

<?xml version="1.0" encoding="utf-8"?> 
<animation-list  
  xmlns:android="http://schemas.android.com/apk/res/android"  
  android:oneshot="false"  >  
       <item android:drawable="@drawable/p1" android:duration="1000"></item>  
       <item android:drawable="@drawable/p2" android:duration="1000"></item>  
       <item android:drawable="@drawable/p3" android:duration="1000"></item>  
       <item android:drawable="@drawable/p4" android:duration="1000"></item>  
</animation-list>

加载资源并应用:

    // Load the ImageView that will host the animation and
    // set its background to our AnimationDrawable XML resource.
    ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
    img.setBackgroundResource(R.drawable.spin_animation);

    // Get the background, which has been compiled to an AnimationDrawable object.
    AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

    // Start the animation (looped playback by default).
    frameAnimation.start();

1.3 补间动画:

补间动画有四种动画形式,分别是:

  • alpha 渐变透明度动画效果
  • scale 渐变尺寸伸缩动画效果
  • translate 画面位置移动动画效果
  • rotate 画面旋转动画效果

可以和帧动画一样在xml中配置动画,例如旋转动画rotate.xml,设置起始和终止的角度,动画中心的相对位置,动画时长等。

<?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android"  
    android:fillAfter = "false"  
    android:zAdjustment="bottom" >  
    <rotate  
        android:fromDegrees="0"  
        android:toDegrees="360"  
        android:pivotX="50%"  
        android:pivotY="50%"  
        android:duration="4000" />  
</set>

使用AnimationUtils加载动画的xml文件生成Animation的实例,也可以在JAVA代码中构造补间动画

// 加载xml构造Animation
Animation anim = AnimationUtils.loadAnimation(mContext, R.anim.rotate);
// 不通过xml构造
Animation rotate = new RotateAnimation(0.0f, +360,  Animation.RELATIVE_TO_SELF, 0.5f, 
                   Animation.RELATIVE_TO_SELF, 0.5f);

Animation类图

1.4 属性动画:

补间动画只能应用于视图(View)对象,动画的方式也仅限于上面所说的四种方式,而属性动画可以应用于所有的Object对象,它通过改变对象的属性值完成动画效果,当然前提是需要有该属性的get和set方法,通过在动画的过程中调用get和set方法改变对象的属性值来完成动画效果。例如通过ObjectAnimator指定要改变的对象和属性名称:

ObjectAnimator animator = ObjectAnimator.ofInt(testObject, "data", 0, 10);
animator.start();

private class TestObject {
    private int data;
    public int getData() {
        return data;
    }
    public void setData(int data) {
        this.data = data;
    }
}

当然也通过ValueAnimator,不需要指定属性名更灵活,设置AnimatorUpdateListener,在动画更新的回调中完成想要的动作,例如,在从0到10的变化过程中,去更新视图的位置?或者其他想要的任何可能操作。

ValueAnimator animator = ValueAnimator.ofInt(0, 10);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    int factor = (Integer) animation.getAnimatedValue();
    }
});

1.5 动画插值:

插值器的作用是根据时间运行的百分比来计算出当前属性改变的百分比,反映的是时间和动画进度(或属性变化)的关系,通过动画当前运行的时间,计算出当前动画的变化量。例如系统预制的线性插值器(LinearInterpolator),时间和动画进度的函数关系是y = x的直线方程,就表示当前动画是均速变化的。而当时间和动画进度的函数关系式表达为y=x^2的时候,那表示动画的变化率随着时间的增加而增加的,在视觉上就表现为加速动画。在理论上就可以通过动画插值器实现不同快慢效果的动画。

加速减速插值器,曲线的斜率是先变大后变小,说明速度是先加速后减速的

在系统预制的插值器有:AccelerateInterpolator(加速插值器),AccelerateDecelerateInterpolator(加速减速插值器), LinearInterpolator(线性插值器),BounceInterpolator(弹跳插值器),AnticipateInterpolator(回荡秋千插值器),AnticipateOvershootInterpolator, CycleInterpolator(正弦周期变化插值器),OvershootInterpolator ,我们也可以通过实现TimeTimeInterpolator或者Interpolatorr接口实现自定义的插值器。

Interpolator类图

1.6 动画估值器

估值器的作用是,根据插值器结果(当前属性变化的百分比)计算出当前属性的值,系统预置的有IntEvaluator(针对整型属性)、FloatEvaluator(针对浮点型属性)和ArgbEvaluator(针对Color属性)。满足的关系是:

二、桌面文件夹伸缩动画

2.1 IOS文件夹动画原理

类似IOS的文件夹视图展开动画,简单说就是针对文件夹视图的一个伸缩动画,而视觉效果上的动画目标就是如何让文件夹的桌面图标和文件夹打开后的视图看起来是一个进行放大缩小的整体,处理伸缩动画的关键:
1.伸缩的前后比例(多少)
2.伸缩视图的中心坐标(相对于哪一点做伸缩)
针对伸缩的比例,应该是文件夹展开前后文件夹内应用图标大小确定的。针对如何确定伸缩视图的中心坐标,就需要首先确定坐标系,就是中心点是相对哪个坐标系确定的!伸缩动画坐标系的的原点在哪里?

  • 伸缩动画的坐标系是由当前缩放视图确定的,当前视图的左上角为坐标系的原点,即(0,0)点。
  • 原点的水平向右方向为横坐标的正方向,平行手机屏幕垂直向下方向未纵坐标的正方向。

确定了伸缩的坐标系,现在的问题就是如何确定伸缩中心点的坐标,在我们学习数学的过程中,老师教我们如何把实际问题抽象成数学问题,就像小学时经典的船在顺流和逆流中航形的问题一样。面对视图的缩放,我们能够想到的应该就是多边形的相似问题,看待现在的文件夹视图,可以抽象成一个矩形,在以矩形的左上角确定的坐标系里,从一个Size放大(或缩小)到另一个Size,在矩形长和宽变化比例相同的情况下,变化前后的矩形就是两个相似矩形,这样就可以很容易的画出下图.

相似矩形

针对相似多边形对应点连线或者反向延长线相交于一点的原理,我们很容易得出下面的关系,即伸缩前后大小、伸缩比例和伸缩点坐标的关系式:

h2 = offset / (1-scale)

通过上面的公式,就很容易计算出文件夹视图伸缩动画的pivotX和pivotY的值计算代码:

// set scale pivotX and pivotY
int leftOffset = folderIconRect.left - folderViewLeft;
int topOffset = folderIconRect.top - folderViewTop;
float height = folderHeight * mFolderScale;
float delta = ((float) folderHeight) / (folderHeight - height);
float folderPivotX = leftOffset * delta;
float folderPivotY = topOffset * delta;

但是这对展开动画仅仅解决缩放动画的问题还原因不够,因为缩放动画只是针对文件夹的视图,而针对文件夹内每个应用图标视图也应该有相应的动画,为什么?因为按照文件夹的位置进行的缩放动画,无法保证文件夹内的应用图标和文件夹图标上应用的缩略图完全重合。联想到学习过的中学物理知识,这个场景就好像你一定能够想到了分运动和合运动,火车在轨道上行驶,人在火车内行走,问人相对与地面的运动是什么样子的?整体文件夹的视图相对于它的伸缩中心点进行伸缩,文件夹视图内的应用图标相对于文件夹视图进行位移,效果又会是什么样子的?想明白这个,相信你一定能感受到选择一个正确的坐标系是多么重要。

文件夹内图标动画效果

抽象出了运动的理论,那计算的思路就是计算出每个应用缩略图标相对于文件夹图标的位置,计算出文件夹展开后每个应用图标相对于文件夹视图的相对位置,接合每个应用图标的伸缩比例,就能得到每个应用图标在文件夹视图的缩放过程中需要完成的位移,简单来说就是Folder的视图在缩放,Folder里的App图标在Folder视图上做相应的位移,结果你会发现是这样:

关闭效果

处理完文件夹视图的问题,相信这个问题已经解决大半了,剩下的就是桌面上其他图标的移动,简单来说还是缩放动画,只需要让每个图标的缩放点和Folder视图的缩放点相对于屏幕坐标系重合就可以了。

2.2 总结

1.处理动画问题首先确定动画起始和终止的状态,根据状态确定动画类型。
2.确定动画坐标系。动画坐标系如何确定取决与动画改变的属性,对于缩放动画,缩放改变是视图本身,那缩放动画的坐标系一定是相对于视图自己建立的,左上角是原点。而对于位移动画,改变translationX和X的值都能实现位置上的改变,但是他们表示的含义不一样,translationX是相对于视图本身而言的,X是相对于父布局而言的,那他们建立的坐标系肯定也不一样。
3.根据建立坐标系完成动画,把复杂的合运动分解成在不同坐标系上的分运动简单求解。

三、参考文档

Android 属性动画(Property Animation) 完全解析 (上)
Android 属性动画(Property Animation) 完全解析 (下)
Android Project Butter分析
http://developer.android.com/reference/android/view/Choreographer.html
http://developer.android.com/reference/android/view/Choreographer.FrameCallback.html
https://github.com/samchen2009/android_uml

转载请标明出处病已blog https://ivonhoe.github.io/