Android动画详解

Android框架提供了两个动画系统,属性动画(property animation )和视图动画(view animation)。在一般情况下我们大多使用属性动画,因为它更灵活,并提供更多的功能。另外,还有一种帧动画,它通过加载图片资源,将多张图片一帧一帧显示形成动画效果。

1.视图动画(View Animation)

视图动画在很早的Android系统中就已提供,它只能用来设置View的动画。视图动画也叫补间动画,通过xml文件或java代码定义。

1-1.属性详解

在补间动画中主要可以实现视图的位移(translate)、缩放(scale)、旋转(rotate)、淡入淡出(alpha)四种效果。其各的主要属性如下:

Animation属性详解

xml属性 java方法 解释
android:detachWallpaper setDetachWallpaper(boolean) 是否在壁纸上运行
android:duration setDuration(long) 动画持续时间,毫秒为单位
android:fillAfter setFillAfter(boolean) 控件动画结束时是否保持动画最后的状态
android:fillBefore setFillBefore(boolean) 控件动画结束时是否还原到开始动画前的状态
android:fillEnabled setFillEnabled(boolean) 与android:fillBefore效果相同
android:interpolator setInterpolator(Interpolator) 设定插值器(指定的动画效果,譬如回弹等)
android:repeatCount setRepeatCount(int) 重复次数
android:repeatMode setRepeatMode(int) 重复类型有两个值,reverse表示倒序回放,restart表示从头播放
android:startOffset setStartOffset(long) 调用start函数之后等待开始运行的时间,单位为毫秒
android:zAdjustment setZAdjustment(int) 表示被设置动画的内容运行时在Z轴上的位置(top/bottom/normal),默认为normal

Alpha属性详解

xml属性 java方法 解释
android:fromAlpha AlphaAnimation(float fromAlpha, …) 动画开始的透明度(0.0到1.0,0.0是全透明,1.0是不透明)
android:toAlpha AlphaAnimation(…, float toAlpha) 动画结束的透明度,同上

Rotate属性详解

xml属性 java方法 解释
android:fromDegrees RotateAnimation(float fromDegrees, …) 旋转开始角度,正代表顺时针度数,负代表逆时针度数
android:toDegrees RotateAnimation(…, float toDegrees, …) 旋转结束角度,正代表顺时针度数,负代表逆时针度数
android:pivotX RotateAnimation(…, float pivotX, …) 缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY RotateAnimation(…, float pivotY) 缩放起点Y坐标,同上规律

Translate属性详解

xml属性 java方法 解释
android:fromXDelta TranslateAnimation(float fromXDelta, …) 起始点X轴坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:fromYDelta TranslateAnimation(…, float fromYDelta, …) 起始点Y轴从标,同上规律
android:toXDelta TranslateAnimation(…, float toXDelta, …) 结束点X轴坐标,同上规律
android:toYDelta TranslateAnimation(…, float toYDelta) 结束点Y轴坐标,同上规律

Scale属性详解

xml属性 java方法 解释
android:fromXScale ScaleAnimation(float fromX, …) 初始X轴缩放比例,1.0表示无变化
android:toXScale ScaleAnimation(…, float toX, …) 结束X轴缩放比例
android:fromYScale ScaleAnimation(…, float fromY, …) 初始Y轴缩放比例
android:toYScale ScaleAnimation(…, float toY, …) 结束Y轴缩放比例
android:pivotX ScaleAnimation(…, float pivotX, …) 缩放起点X坐标(数值、百分数、百分数p,譬如50表示以当前View左上角坐标加50px为初始点、50%表示以当前View的左上角加上当前View宽高的50%做为初始点、50%p表示以当前View的左上角加上父控件宽高的50%做为初始点)
android:pivotY ScaleAnimation(…, float pivotY) 缩放起点Y坐标,同上规律

1-2.xml文件中定义

1.xml定义动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:fromXScale="1.0"
        android:toXScale="1.4"
        android:fromYScale="1.0"
        android:toYScale="0.6"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false"
        android:duration="700" />
</set>

2.在java中使用动画资源

Animation animation = AnimationUtils.loadAnimation(context,R.anim.view_anin);
        image.startAnimation(animation);

1-3.java文件中定义

RotateAnimation rotateAnimation = new RotateAnimation(0,180);
        rotateAnimation.setDuration(400);
        image.startAnimation(rotateAnimation);

2.帧动画(Drawable Animation)

它通过加载图片资源,将多张图片一帧一帧显示形成动画效果。在Android中提供了两种方式为AnimationDrawable添加帧:XML定义的资源文件和Java代码创建。

2-1.AnimationDrawable的常用方法:

  • void start():开始播放逐帧动画。
  • void stop():停止播放逐帧动画。
  • void addFrame(Drawable frame,int duration):为AnimationDrawable添加一帧,并设置持续时间。
  • int getDuration(int i):得到指定index的帧的持续时间。
  • Drawable getFrame(int index):得到指定index的帧Drawable。
  • int getNumberOfFrames():得到当前AnimationDrawable的所有帧数量。
  • boolean isOneShot():当前AnimationDrawable是否执行一次,返回true执行一次,false循环播放。
  • boolean isRunning():当前AnimationDrawable是否正在播放。
  • void setOneShot(boolean oneShot):设置AnimationDrawable是否执行一次,true执行一次,false循环播放。

2-2.在xml文件中定义资源文件

1.xml文件中定义

<?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/loading_1" android:duration="100"/>
    <item android:drawable="@drawable/loading_2" android:duration="100"/>
    <item android:drawable="@drawable/loading_3" android:duration="100"/>
    <item android:drawable="@drawable/loading_4" android:duration="100"/>
    <item android:drawable="@drawable/loading_5" android:duration="100"/>
    <item android:drawable="@drawable/loading_6" android:duration="100"/>
    <item android:drawable="@drawable/loading_7" android:duration="100"/>
    <item android:drawable="@drawable/loading_8" android:duration="100"/>
    <item android:drawable="@drawable/loading_9" android:duration="100"/>
    <item android:drawable="@drawable/loading_10" android:duration="100"/>
    <item android:drawable="@drawable/loading_11" android:duration="100"/>
    <item android:drawable="@drawable/loading_12" android:duration="100"/>

</animation-list>

2.在java中调用

// 通过逐帧动画的资源文件获得AnimationDrawable示例
        AnimationDrawable animationDrawable =(AnimationDrawable) getResources().getDrawable(R.drawable.animation_loading);
        image.setImageDrawable(animationDrawable);
        animationDrawable.start();

2-3.使用java定义资源文件

  AnimationDrawable drawable = new AnimationDrawable();
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_1),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_2),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_3),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_4),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_5),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_6),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_7),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_8),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_9),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_10),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_11),100);
        drawable.addFrame(getResources().getDrawable(R.drawable.loading_12),100);
        drawable.setOneShot(true);
        image.setImageDrawable(drawable);
        drawable.start();

3.属性动画(Property Animation)

属性动画只对Android 3.0(API 11)以上版本的Android系统才有效,这种动画可以设置给任何Object,包括那些还没有渲染到屏幕上的对象。这种动画是可扩展的,可以让你自定义任何类型和属性的动画。

3-1.属性动画允许我们定义以下的动画特点:

  • Duration:可以指定动画的持续时间。默认长度为300毫秒;
  • Time interpolation:可以指定该属性的值如何作为动画的当前的运行时间的函数来计算;
  • Repeat count and behavior:指定动画的播放次数,还可定义是否反向播放动画;
  • Animator sets:动画集合,即可以同时对一个对象应用多个动画,这些动画可以同时播放也可以对不同动画设置不同的延迟;
  • Frame refresh dela:多少时间刷新一次动画,即每隔多少时间计算一次属性值,默认10ms。最终取决于系统整体多么繁忙,系统如何能够快速的服务基础计时器。

3-1.属性动画的工作原理:

3-1-1.实例描述
图1. Example of a linear animation

如图1所示的就是一个线性动画实例,描述了一个Object的x属性随时间匀速增长,也就是x方向的坐标每10ms就移动10个像素。


图2.Example of a non-linear animation

如图2所示的是一个非线性动画实例,Object的x属性同样是没10ms刷新一次,但在开始的时候,这个动画加速到中间点,然后从中途减速,直至动画结束。

3-1-2.属性动画主类之间的相互合作
图3.How animations are calculated

ValueAnimator:是动画的执行类,跟踪动画的时间,并且它是动画的属性的当前值。

  • TimeInterpolatorValueAnimator封装了动画的TimeInterpolator时间插值器,定义动画的插入。
  • TypeEvaluator:用于设置动画属性的值

要启动动画,需要创建一个ValueAnimator,并且指定目标对象属性的开始、结束值和持续时间。在调用start后,整个动画过程中, ValueAnimator会根据已经完成的动画时间计算得到一个0到1之间的分数,代表该动画的已完成动画百分比。0表示0%,1表示100%。

当ValueAnimator计算完已完成动画分数后,它会调用当前设置的TimeInterpolator,去计算得到一个interpolated(插值)分数,在计算过程中,已完成动画百分比会被加入到新的插值计算中。

当插值分数计算完成后,ValueAnimator会根据插值分数调用合适的 TypeEvaluator去计算运动中的属性值。

3-2.属性动画的具体使用:

3-2-1.ValueAnimator

ValueAnimator是属性动画的核心类,但平时用的时候好像不常接触。使用的时候需要添加监听AnimatorUpdateListener监听,在监听方法中对需要执行动画的对象设置当前的属性值。

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();
animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});
3-2-2.ObjectAnimator

ObjectAnimator是ValueAnimator的一个子类,相对于ValueAnimatorObjectAnimator我们会用得更多一点。

使用:

ObjectAnimator.ofFloat(textview,"rotationX",0.0f,180f)
              .setDuration(100)
              .start();

对于ObjectAnimator..ofFloat(Object target,String propertyName,float... values),其中第一个参数代表需要作用到的View身上,第二个参数代表需要执行的动画的属性名,第三个可变参数代表属性值。
需要注意参数名不要写错,不过可以写一个该动画没有的属性,然后自己在AnimatorUpdateListeneronAnimationUpdate方法中设置多种属性值,一次性实现淡入淡出、翻转等多种效果,自己手动调用,如:

 ObjectAnimator anim = ObjectAnimator//  
            .ofFloat(view, "zhy", 1.0F,  0.0F)//  
            .setDuration(500);//  
    anim.start();  
    anim.addUpdateListener(new AnimatorUpdateListener()  
    {  
        @Override  
        public void onAnimationUpdate(ValueAnimator animation)  
        {  
            float cVal = (Float) animation.getAnimatedValue();  
            view.setAlpha(cVal);  
            view.setScaleX(cVal);  
            view.setScaleY(cVal);  
        }  
    });  
3-2-3.AnimatorSet组合动画

在很多情况下,我们不可能只对对象执行一种动画,可能需要移动的时候还要翻转,或者淡入淡出。Android系统就为我们提供了AnimatorSet这个类,并且会提供了以下四个方法帮助我们进行动画的组合:

  • after(Animator anim) 将现有动画插入到传入的动画之后执行
  • after(long delay) 将现有动画延迟指定毫秒后执行
  • before(Animator anim) 将现有动画插入到传入的动画之前执行
  • with(Animator anim) 将现有动画和传入的动画同时执行

使用

        ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
        ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
        ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);

        AnimatorSet animSet = new AnimatorSet();
        animSet.play(rotate).with(fadeInOut).after(moveIn);

        //三个动画同时执行
        //animSet.playTogether(moveIn,rotate,fadeInOut);

        animSet.setDuration(5000);
        animSet.start();
3-2-4.使用xml声明动画

通过自定义的xml进行声明动画,可以进行动画的重用,更轻松地编辑动画序列。
为了区分使用来自那些使用传统的新属性动画的API动画文件(视图动画)框架,从Android 3.1开始,属性动画的xml文件应保存在res/animator/目录下。

使用:
1.xml文件:

<?xml version="1.0" encoding="utf-8"?>  
<set xmlns:android="http://schemas.android.com/apk/res/android"  
    android:ordering="together" >  
  
    <objectAnimator  
        android:duration="1000"  
        android:propertyName="scaleX"  
        android:valueFrom="1"  
        android:valueTo="0.5" >  
    </objectAnimator>  
    <objectAnimator  
        android:duration="1000"  
        android:propertyName="scaleY"  
        android:valueFrom="1"  
        android:valueTo="0.5" >  
    </objectAnimator>  
  
</set>  

2.java:中调用

        // 加载动画  
        Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);  
        mMv.setPivotX(0);  
        mMv.setPivotY(0);  
        //显示的调用invalidate  
        mMv.invalidate();  
        anim.setTarget(mMv);  
        anim.start();  

3-3.Animator监听器

Animator提供了一个addListener()的方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。

anim.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {
                //动画启动时调用
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                //当动画结束时调用
            }

            @Override
            public void onAnimationCancel(Animator animation) {
                //当动画被取消调用,被取消的动画还会调用onAnimationEnd方法
            }

            @Override
            public void onAnimationRepeat(Animator animation) {
                //当动画重演调用
            }
        });

最后再了解一下插值器和估值器。

4.插值器(Interpolator)与估值器(TypeEvaluator)

插值器和估值器都是实现复杂动画的关键。其中插值器主要用来设置 属性值 从初始值过渡到结束值 的变化规律 ,如加速,回弹等效果。估值器设置 属性值 从初始值过渡到结束值 的变化具体数值 。插值器(Interpolator)决定 值 的变化规律(匀速、加速blabla),即决定的是变化趋势;而接下来的具体变化数值则交给
而估值器 。

插值器(Interpolator)

Android系统为我们提供了九种内置的插值器,如下表:

xml资源ID java类 描述
@android:anim/accelerate_interpolator AccelerateInterpolator 动画加速进行
@android:anim/overshoot_interpolator OvershootInterpolator 快速完成动画,超出再回到结束样式
@android:anim/accelerate_decelerate_interpolator AccelerateDecelerateInterpolator 先加速再减速
@android:anim/anticipate_interpolator AnticipateInterpolator 先退后再加速前进
@android:anim/anticipate_overshoot_interpolator AnticipateOvershootInterpolator 先退后再加速前进,超出终点后再回终点
@android:anim/bounce_interpolator BounceInterpolator 最后阶段弹球效果
@android:anim/cycle_interpolator CycleInterpolator 周期运动
@android:anim/decelerate_interpolator DecelerateInterpolator 减速
@android:anim/linear_interpolator LinearInterpolator 匀速

插值器在动画的使用有xml和java两种方式。

在xml中使用:

1.设置插值器 android:interpolator属性

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:fromXScale="1.0"
        android:toXScale="1.4"
        android:fromYScale="1.0"
        android:toYScale="0.6"
        android:pivotX="50%"
        android:pivotY="50%"
        android:fillAfter="false"
        android:duration="700" />
    <set android:interpolator="@android:anim/decelerate_interpolator">
        <scale
            android:fromXScale="1.4"
            android:toXScale="0.0"
            android:fromYScale="0.6"
            android:toYScale="0.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:startOffset="700"
            android:duration="400"
            android:fillBefore="false" />
        <rotate
            android:fromDegrees="0"
            android:toDegrees="-45"
            android:toYScale="0.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:startOffset="700"
            android:duration="400" />
    </set>
</set>

2.在java中调用

Animation animation = AnimationUtils.loadAnimation(context,R.anim.view_anin);
        image.startAnimation(animation);

其实就是在上面的补间动画里加了个android:interpolator属性就是。

在java中使用

TranslateAnimation rotateAnimation = new TranslateAnimation(0,200,0,200);
        rotateAnimation.setDuration(400);
        //创建对于的插值器
        OvershootInterpolator interpolator = new OvershootInterpolator();
        //设置插值器
        rotateAnimation.setInterpolator(interpolator);
        image.startAnimation(rotateAnimation);

自定义插值器

本质:根据动画的进度(0%-100%)计算出当前属性值改变的百分比。
补间动画实现Interpolator接口。
属性动画实现TimeInterpolator接口。

实现Interpolator接口
public class MyInterpolator implements Interpolator {

    @Override
    public float getInterpolation(float input) {
        Log.d("print", "getInterpolation: " + input);
        return input;
    }
}
实现TimeInterpolator接口

public class MyInterpolator implements TimeInterpolator {

    @Override
    public float getInterpolation(float input) {
          Log.d("print", "getInterpolation: " + input);
        return input;
    }
}

其中input为0~1.0之前的数字,表示当前属性变化的百分比。返回的值就是用于估值器继续计算的fraction值,可以大于1。如:当你return为0时,动画将静止在初始位置。当你return为1时,动画开始后将跳到你设置的终止位置停留知道动画时间停止后回到初始位置。

估值器(TypeEvaluator)

系统内置了3个估值器,分别是:

  • IntEvaluator:整数属性值。
  • FloatEvaluator:浮点型属性值。
  • ArgbEvaluator:十六进制color属性值。

使用:

ObjectAnimator objectAnimator = ObjectAnimator.ofObject(image,"alpha",new IntEvaluator(),1,0,1);
        objectAnimator.setDuration(500);
        objectAnimator.start();

自定义估值器:

需要实现TypeEvaluator接口:

public class MyTypeEvaluator implements TypeEvaluator {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        // fraction:插值器getInterpolation()的返回值
        // startValue:动画的初始值
        // endValue:动画的结束值
        Log.d("print", "fraction: " + fraction + "\nstartValue "+ startValue + " \nendValue" + endValue);
        return ((Integer)startValue + ((Integer)endValue - (Integer)startValue) * fraction);
    }
}

本文参考文章:
Android应用开发之所有动画使用详解
Android属性动画详解
Android插值器与估值器分析
官网文档:android developer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,513评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,312评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,124评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,529评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,937评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,913评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,084评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,816评论 0 205
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,593评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,788评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,267评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,601评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,265评论 3 241
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,158评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,953评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,066评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,852评论 2 277

推荐阅读更多精彩内容

  • 本文主要是针对android 中的动画进行详细描述,并简单分析原理;一、概述Android动画分为三种:帧动画(F...
    暮染1阅读 701评论 0 0
  • 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今...
    未聞椛洺阅读 2,582评论 0 9
  • 转载一篇高质量博文,原地址请戳这里转载下来方便今后查看。1 背景不能只分析源码呀,分析的同时也要整理归纳基础知识,...
    Elder阅读 1,899评论 0 24
  • 转载▼ it分类:IOS开发相关 下面是官方的说明: 源字符串--->结果字符串 “/tmp/scratch.ti...
    沐阳风色阅读 269评论 0 0
  • 任我行心里话: 朋友你好,我是任我行。在提笔写这封信时内心久久不能平静,因为今天对任我行对学操盘训练营都是一种磨练...
    sadhusun阅读 1,554评论 10 8