Android中的动画分为视图动画(View Animation)、属性动画(Property Animation)以及Drawable动画。从Android 3.0(API Level 11)開始。Android開始支持属性动画,本文主要解说怎样使用属性动画。

关于视图动画能够參见博文《Android四大视图动绘图文具体解释》


概述

视图动画局限比較大。例如以下所述:

  1. 视图动画仅仅能使用在View上面。

  2. 视图动画并没有真正改变View相应的属性值,这导致了UI效果与实际View状态存在差异。并导致了一系列怪异行为,比方在使用了视图动画TranslateAnimation的View的UI上对其触摸,你可能吃惊地发现并没有触发触摸事件。

鉴于视图动画以上缺陷。从Android 3.0引入了属性动画。属性动画具有以下特性:

  1. 属性动画应用面更广。不仅仅应用于View,能够将其应用到随意的对象上面。且该对象不须要具有UI界面。

  2. 当将属性动画作用于某个对象时,能够通过调用对象的setXXX方法实际改变对象的值。所以,当将属性动画作用于某个View时,View对象相应的属性值会被改变。

我们看一下属性动画时怎样工作的。

事实上属性动画的工作原理并不复杂,假设一个对象有一个属性x。我们想通过属性动画动态更改该值,假设我们想在40ms内将x的值从0渐变到40,那么例如以下图所看到的:

随着时间的增长,相应的x值也相应地线性渐变。当动画完毕时,x的值就是我们设置的终于值40。假设x值线性渐变。那么x的变化速度就是匀速的。事实上,我们也能够变速地改变x的值,这会我们能够一開始加速增加x的值,后面减速增加x的值。例如以下图所看到的:



如上图所看到的,在前20ms。x值加速增大,在后20ms。x值增大的速度减少。

事实上。每种改变x值速度的方式都叫做时间插值器TimeInterpolator,第一张图中使用的时间插值器叫做LinearInterpolator,第二张图中使用的时间插值器叫做AccelerateDecelerateInterpolator。动画開始后,时间插值器会依据相应的算法计算出某一时刻x的值。然后我们就能够用该计算出的值更新对象中x属性的值,这就是属性动画的基本工作原理。

属性动画中基本的类例如以下图所看到的:

以下会对上述类分别进行解说。


Animator

属性动画基本的类都在android.animation命名空间下,Animator是属性动画的基类。其是一个抽象类。该类定义了很多重要的方法,例如以下所看到的:

  • setDuration(long duration)

    通过setDuration方法能够设置动画总共的持续时间。以毫秒为单位。

  • start()

    通过start方法能够启动动画。动画启动后不一定会马上运行。假设之前通过调用setStartDelay方法设置了动画延迟时间,那么会在经过延迟时间之后再运行动画;假设没有设置过动画的延迟时间,那么动画在调用了start()方法之后会马上运行。

    在调用了start()方法之后。动画的isStarted()方法就会返回true;在动画真正运行起来之后,动画的isRunning()方法就会返回true,这时候动画才会调用TimeInterpolator才開始工作计算属性在某个时刻的值。调用动画的start()方法所在的线程必须绑定了一个Looper对象,假设没有绑定就会报错。

    当然,UI线程(即主线程)早就默认绑定了一个Looper对象,所以在主线程中我们就无需操心这个问题。假设我们想在一个View上使用属性动画。那么我们应该保证我们是在UI线程上调用的动画的start()方法。start()方法运行后会触发动画监听器AnimatorListener的onAnimationStart方法的运行。

  • setStartDelay(long startDelay)

    能够通过调用setStartDelay方法设置动画的延迟运行时间,比方调用setStartDelay(1000)意味着动画在运行了start()方法1秒之后才真正运行。这样的情况下,在调用了start()方法之后,isStarted()方法返回true,表示动画已经启动了,可是在start()方法调用后1s内,isRunning()方法返回false。表示动画还未真正运行。比方在start()方法调用后第0.5秒,因为动画还在延迟阶段,所以isRunning()返回false;在start()方法运行1秒之后。isStarted()方法还是返回true。isRunning()方法也返回了true。表示动画已经真正開始运行了。通过调用getStartDelay()方法能够返回我们设置的动画延迟启动时间,默认值是0。

  • setInterpolator(TimeInterpolator value)

    我们能够通过调用setInterpolator方法改变动画所使用的时间插值器,因为视图动画也须要使用时间插值器,所以我们能够使用android.view.animation命名空间下的一系列插值器,将其与属性动画一起工作。通过动画的getInterpolator方法能够获取我们设置的时间插值器。

  • setTarget(Object target)

    能够通过调用动画的setTarget方法设置其要操作的对象,这样能够更新该对象的某个属性值。实际上,该方法对于ValueAnimator作用不大,因为ValueAnimator不是直接与某个对象打交道的。

    setTarget方法对于ObjectAnimator作用较大,因为ObjectAnimator须要绑定某个要操作的对象,以下会具体介绍。

  • pause()

    Android中API Level 19在Animator中增加了pause()方法,该方法能够暂停动画的运行。调用pause()方法的线程必须与调用start()方法的线程是同一个线程。

    假设动画还没有运行start()或者动画已经结束了,那么调用pause()方法没有不论什么影响,直接被忽略。

    当运行了pause()方法后,动画的isPaused()方法会返回true。

    pause()方法运行后会触发动画监听器AnimatorPauseListener的onAnimationPause方法的运行。

  • resume()

    假设动画通过调用pause()方法暂停了。那么之后能够通过调用resume()方法让动画从上次暂停的地方继续运行。

    resume()方法也是从API Level 19引入的,而且调用resume()方法的线程必须与调用start()方法的线程是同一个线程。假设动画没有处于暂停状态(即isPaused()返回false)。那么调用resume()方法会被忽略。resume()方法运行后会触发动画监听器AnimatorPauseListener的onAnimationResume方法的运行。

  • end

    end()方法运行后。动画会结束运行。直接从当前状态跳转到终于的完毕状态,并将属性值分配成动画的终止值,并触发动画监听器AnimatorListener的onAnimationEnd方法的运行。

  • cancel()

    cancel()方法运行后,动画也会结束运行,可是与调用end方法不同的是,其不会将属性值分配给动画的终止值。

    比方一个动画在400ms内将对象的x属性从0渐变为40。当运行到第200ms时调用了cancel()方法。那么属性x的终于值是20,而不是40,这是与调用end()方法不同的,假设在第200ms调用了end()方法,那么属性x的终于值是40。

    调用cancel()方法后。会先触发AnimatorListener的onAnimationCancel方法的运行,然后触发onAnimationEnd方法的运行。

  • clone()

    Animator实现了java.lang.Cloneable接口。Animator的clone()方法会对动画进行拷贝,可是该方法默认实现的仅仅是浅拷贝,子类能够重写该方法以实现深拷贝。

  • addListener (Animator.AnimatorListener listener)

    能够通过addListener方法向Animator增加动画监听器,该方法接收的是AnimatorListener接口类型的參数,其具有四个方法:onAnimationStart、onAnimationCancel、onAnimationEnd、onAnimationRepeat。我们上面已经介绍了前三个方法,onAnimationRepeat方法会在动画在反复播放的时候被回调。Android中的AnimatorListenerAdapter类是个抽象类。事实上现了AnimatorListener接口。并为全部方法提供了一个空实现。

  • addPauseListener (Animator.AnimatorPauseListener listener)

    能够通过addPauseListener方法能够向Animator增加动画暂停相关的监听器。该方法接收的是AnimatorPauseListener接口类型的參数,具有两个方法:onAnimationPause和onAnimationResume。上面已经提到过,在此不再赘述。AnimatorListenerAdapter相同也实现了AnimatorPauseListener接口,并为全部方法提供了一个空实现。


ValueAnimator

ValueAnimator继承自抽象类Animator。要让属性动画渐变式地更改对象中某个属性的值,可分两步操作:第一步,动画须要计算出某一时刻属性值应该是多少;第二步,须要将计算出的属性值赋值给动画的属性。ValueAnimator仅仅实现了第一步,也就是说ValueAnimator仅仅负责以动画的形式不断计算不同一时候刻的属性值,但须要我们开发人员自己写代码将计算出的值通过对象的setXXX等方法更新对象的属性值。

ValueAnimator中有两个比較重要的属性。一个是TimeInterpolator类型的属性,还有一个是TypeEvaluator类型的属性。TimeInterpolator指的就是时间插值器。在上面我们已经介绍过,在此不再赘述。

TypeEvaluator是什么呢?TypeEvaluator表示的是ValueAnimator对哪种类型的值进行动画处理。

ValueAnimator提供了四个静态方法ofFloat()、ofInt()、ofArgb()和ofObject(),通过这四个方法能够对不同种类型的值进行动画处理。这四个方法相应了四种TypeEvaluator。以下会具体说明。

  • public static ValueAnimator ofFloat (float… values)

    ofFloat方法接收一系列的float类型的值。其内部使用了FloatEvaluator。

    通过该方法ValueAnimator能够对float值进行动画渐变。其用法例如以下所看到的:

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 500f);
    
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    float deltaY = (float)animation.getAnimatedValue();
    textView.setTranslationY(deltaY);
    }
    }); //默认duration是300毫秒
    valueAnimator.setDuration(3000);
    valueAnimator.start();

    其效果例如以下所看到的:

    我们通过构造函数指定了动画的起始值为0,终止值为500。动画的默认持续时间是300毫秒,我们通过setDuration()方法设置为3000毫秒。

    该动画会在3秒内。将值从0到500动画渐变。

    ValueAnimator提供了一个addUpdateListener方法,能够通过该方法向其增加AnimatorUpdateListener类型的监听器。

    AnimatorUpdateListener有一个onAnimationUpdate方法。ValueAnimator会每隔一定时间(默认间隔10ms)计算属性的值,每当计算的时候就会回调onAnimationUpdate方法。在该方法中,我们通过调用ValueAnimator的getAnimatedValue()方法获取到当前动画计算出的属性值,然后我们将该值传入textView的setTranslationY()方法中,从而更新了textView的位置,这样就通过ValueAnimator以动画的形式移动textView。

  • public static ValueAnimator ofInt (int… values)

    ofInt方法与ofFloat方法非常相似,仅仅只是ofInt方法接收int类型的值,ofInt方法内部使用了IntEvaluator,其具体使用可參考上面ofFloat的使用代码。在此不再赘述。

  • public static ValueAnimator ofArgb (int… values)

    从API Level 21開始,ValueAnimator中增加了ofArgb方法,该方法接收一些列代表了颜色的int值。其内部使用了ArgbEvaluator。能够用该方法实现将一个颜色动画渐变到还有一个颜色,我们从中能够不断获取中间动画产生的颜色值。你可能纳闷,既然传入的还是int值,那直接用ofInt方法不即可了吗,干嘛还要新增一个ofArgb方法呢?实际上用ofInt方法是不能完毕颜色动画渐变的。

    我们知道一个int值包括四个字节,在Android中第一个字节代表Alpha分量,第二个字节代表Red分量。第三个字节代表Green分量,第四个字节代表Blue分量,且我们经常使用16进制表示颜色。这样看起来更明显易懂一些,比方int值0xffff0000表示的红色,0xff00ff00表示的是绿色,最前面的ff表示的是Alpha。ofArgb方法会通过ArgbEvaluator将颜色拆分成四个分量,然后分别对各个分量进行动画计算。然后将四个计算完的分量再又一次组合成一个表示颜色的int值。这就是ofArgb方法的工作原理。用法例如以下所看到的:

        //ValueAnimator.ofArgb()方法是在API Level 21中才增加的
    if(Build.VERSION.SDK_INT >= 21){
    //起始颜色为红色
    int startColor = 0xffff0000;
    //终止颜色为绿色
    int endColor = 0xff00ff00;
    ValueAnimator valueAnimator = ValueAnimator.ofArgb(startColor, endColor);
    valueAnimator.setDuration(3000);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    int color = (int)animation.getAnimatedValue();
    textView.setBackgroundColor(color);
    }
    });
    valueAnimator.start();
    }

    效果例如以下所看到的:

    我们将TextView的颜色通过动画从红色渐变到绿色。

  • public static ValueAnimator ofObject (TypeEvaluator evaluator, Object… values)

    因为我们要进行动画处理的值是各种各样的。可能不是float、int或颜色值,那我们怎么使用属性动画呢?为此,ValueAnimator提供了一个ofObject方法,该方法接收一个TypeEvaluator类型的參数,我们须要实现该接口TypeEvaluator的evaluate方法,仅仅要我们实现了TypeEvaluator接口,我们就能通过ofObject方法处理随意类型的数据。

    我们之前提到ofArgb方法是从API Level 21才引入的。假设我们想在之前的这之前的版本号中使用ofArgb的功能,怎么办呢?我们能够扩展TypeEvaluator,从而通过ofObject方法实现ofArgb方法的逻辑,例如以下所看到的:

        //起始颜色为红色
    int startColor = 0xffff0000;
    //终止颜色为绿色
    int endColor = 0xff00ff00;
    ValueAnimator valueAnimator = ValueAnimator.ofObject(new TypeEvaluator() {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
    //从初始的int类型的颜色值中解析出Alpha、Red、Green、Blue四个分量
    int startInt = (Integer) startValue;
    int startA = (startInt >> 24) & 0xff;
    int startR = (startInt >> 16) & 0xff;
    int startG = (startInt >> 8) & 0xff;
    int startB = startInt & 0xff; //从终止的int类型的颜色值中解析出Alpha、Red、Green、Blue四个分量
    int endInt = (Integer) endValue;
    int endA = (endInt >> 24) & 0xff;
    int endR = (endInt >> 16) & 0xff;
    int endG = (endInt >> 8) & 0xff;
    int endB = endInt & 0xff; //分别对Alpha、Red、Green、Blue四个分量进行计算,
    //终于合成一个完整的int型的颜色值
    return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
    (int)((startR + (int)(fraction * (endR - startR))) << 16) |
    (int)((startG + (int)(fraction * (endG - startG))) << 8) |
    (int)((startB + (int)(fraction * (endB - startB))));
    }
    }, startColor, endColor);
    valueAnimator.setDuration(3000);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
    int color = (int)animation.getAnimatedValue();
    textView.setBackgroundColor(color);
    }
    });
    valueAnimator.start();

    以上代码实现的效果与ofArgb实现的效果是一样的。都是将TextView从红色渐变到绿色,就不再附图了。可是我们能够在API Level 11及以后的版本号中都能够使用以上ofObject的代码,通用性更强。


ObjectAnimator

ObjectAnimator继承自ValueAnimator。我们之前提到,要让属性动画渐变式地更改对象中某个属性的值,可分两步操作:第一步。动画须要计算出某一时刻属性值应该是多少;第二步,须要将计算出的属性值赋值给动画的属性。

ValueAnimator仅仅实现了第一步,也就是说ValueAnimator仅仅负责以动画的形式不断计算不同一时候刻的属性值,但须要我们开发人员自己写代码在动画监听器AnimatorUpdateListener的onAnimationUpdate方法中将计算出的值通过对象的setXXX等方法更新对象的属性值。ObjectAnimator比ValueAnimator更进一步,其会自己主动调用对象的setXXX方法更新对象中的属性值。

ObjectAnimator重载了ofFloat()、ofInt()、ofArgb()和ofObject()等静态方法,我们以下依次说明。

  • ofFloat(Object target, String propertyName, float… values)

    用法例如以下所看到的:

        float value1 = 0f;
    float value2 = 500f;
    final ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(textView, "translationY", value1, value2);
    objectAnimator.setDuration(3000);
    objectAnimator.start();

    以上代码实现的效果与通过ValueAnimator的ofFloat方法实现的效果相同,此处不再附图,可是能够看出使用ObjectAnimator代码更简洁。在构造函数中。我们将textView作为target传递给ObjectAnimator。然后指定textView要变化的属性是translationY,最后指定渐变范围是从0到500。当动画開始时,ObjectAnimator就会不断调用textView的setTranslationY方法以更新其值。我们此处演示的是ObjectAnimator与View一起工作,事实上ObjectAnimator能够与随意的Object对象工作。假设要更新某个对象中名为propery的属性,那么该Object对象必须具有一个setProperty的setter方法能够让ObjectAnimator调用。

    在ofFloat方法最后假设仅仅填入了一个float值,那么ObjectAnimator须要调用对象的getXXX方法获取对象初始的属性值,然后从该初始的属性值渐变到终止值。

  • ofInt(Object target, String propertyName, int… values)

    參见ofFloat的用法。

  • ofArgb(Object target, String propertyName, int… values)

    使用代码例如以下所看到的:

        //ObjectAnimator.ofArgb()方法是在API Level 21中才增加的
    if(Build.VERSION.SDK_INT >= 21){
    int startColor = 0xffff0000;
    int endColor = 0xff00ff00;
    ObjectAnimator objectAnimator = ObjectAnimator.ofArgb(textView, "backgroundColor", startColor, endColor);
    objectAnimator.setDuration(3000);
    objectAnimator.start();
    }

    效果图參见ValueAnimator中相应的图片。

  • ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object… values)

    使用代码例如以下所看到的:

        int startColor = 0xffff0000;
    int endColor = 0xff00ff00;
    ObjectAnimator objectAnimator = ObjectAnimator.ofObject(textView, "backgroundColor", new TypeEvaluator() {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
    int startInt = (Integer) startValue;
    int startA = (startInt >> 24) & 0xff;
    int startR = (startInt >> 16) & 0xff;
    int startG = (startInt >> 8) & 0xff;
    int startB = startInt & 0xff; int endInt = (Integer) endValue;
    int endA = (endInt >> 24) & 0xff;
    int endR = (endInt >> 16) & 0xff;
    int endG = (endInt >> 8) & 0xff;
    int endB = endInt & 0xff; return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
    (int)((startR + (int)(fraction * (endR - startR))) << 16) |
    (int)((startG + (int)(fraction * (endG - startG))) << 8) |
    (int)((startB + (int)(fraction * (endB - startB))));
    }
    }, startColor, endColor);
    objectAnimator.setDuration(3000);
    objectAnimator.start();

    效果图參见ValueAnimator中相应的图片。


AnimatorSet

AnimatorSet继承自Animator。AnimatorSet表示的是动画的集合,我们能够通过AnimatorSet把多个动画集合在一起,让其串行或并行运行,从而创造出复杂的动画效果。

我们想让TextView先进行旋转,然后进行平移,最后进行伸缩,我们能够通过AnimatorSet实现该效果,代码例如以下所看到的:

```
//anim1实现TextView的旋转动画
Animator anim1 = ObjectAnimator.ofFloat(textView, "rotation", 0f, 360f);
anim1.setDuration(2000);
//anim2和anim3TextView的平移动画
Animator anim2 = ObjectAnimator.ofFloat(textView, "translationX", 0f, 300f);
anim2.setDuration(3000);
Animator anim3 = ObjectAnimator.ofFloat(textView, "translationY", 0f, 400f);
anim3.setDuration(3000);
//anim4实现TextView的伸缩动画
Animator anim4 = ObjectAnimator.ofFloat(textView, "scaleX", 1f, 0.5f);
anim4.setDuration(2000); //第一种方式
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(anim1, anim2, anim4);
animatorSet.playTogether(anim2, anim3);
animatorSet.start(); //另外一种方式
/*AnimatorSet anim23 = new AnimatorSet();
anim23.playTogether(anim2, anim3);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playSequentially(anim1, anim23, anim4);
animatorSet.start();*/ //第三种方式
/*AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(anim1).before(anim2);
animatorSet.play(anim2).with(anim3);
animatorSet.play(anim4).after(anim2);
animatorSet.start();*/
```

效果例如以下所看到的:

动画anim1用于旋转TextView。anim2用于在X轴方向偏移TextView,anim3用于在Y轴方向偏移TextView,anim4用于缩放TextView。

我们在以上代码中提供了三种方式通过AnimationSet把这四个动画组合到一起,另外一种方式和第三种方式被凝视起来了。

事实上有非常多种办法实现上述效果。这里仅仅介绍一下上述三种方式的思路。

  1. 在第一种方式中。调用了animatorSet.playSequentially(anim1, anim2, anim4),该方法将anim1、anim2以及anim4按顺序串联起来放到了animatorSet中,这样首先会让动画anim1运行。anim1运行完毕后,会依次运行动画anim2,运行完anim2之后会运行动画anim3。通过调用animatorSet.playTogether(anim2, anim3)。保证了anim2和anim3同一时候运行,即动画anim1完毕之后会同一时候运行anim2和anim3。

  2. 在另外一种方式中,我们首先创建了一个AnimatorSet变量anim23。然后通过anim23.playTogether(anim2, anim3)将anim2和anim3组合成一个小的动画集合。

    然后我们再把anim1、anim23以及anim4一起传入到animatorSet.playSequentially(anim1, anim23, anim4)中。这样anim1、anim23、anim4会依次运行,而anim23中的anim2和anim3会同一时候运行。该方式同一时候也演示了能够将一个AnimatorSet作为动画的一部分放入还有一个AnimatorSet中。

  3. 在第三种方式中,我们使用了AnimatorSet的play方法,该方法返回AnimatorSet.Builder类型,animatorSet.play(anim1).before(anim2)确保了anim1运行完了之后运行anim2,animatorSet.play(anim2).with(anim3)确保了anim2和anim3同一时候运行,animatorSet.play(anim4).after(anim2)确保了anim2运行完了之后运行anim4。

    须要说明的是animatorSet.play(anim1).before(anim2)与animatorSet.play(anim2).after(anim1)是全然等价的,之所以在上面代码中有的写before,有的写after,仅仅是为了让大家多了解一下API。

希望本文对大家学习属性动画有所帮助。

Android图文具体解释属性动画的更多相关文章

  1. Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果

    1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...

  2. Android属性动画完全解析(上),初识属性动画的基本用法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系 ...

  3. Android属性动画完全解析(上)

    Android属性动画完全解析(上) 转载:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷 ...

  4. Android(java)学习笔记263:Android下的属性动画(Property Animation)

    1. 属性动画(Property Animation)引入: 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(fra ...

  5. Android(java)学习笔记207:Android下的属性动画(Property Animation)

    1. 属性动画(Property Animation)引入: 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(fra ...

  6. Android属性动画-基本用法

    在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始的时候就给我们提供了两种实现动画效果的方式,逐帧动画(frame-by-frame animation)和补间动画(twe ...

  7. Android属性动画完全解析

    转载:http://blog.csdn.net/guolin_blog/article/details/43536355 在手机上去实现一些动画效果算是件比较炫酷的事情,因此Android系统在一开始 ...

  8. 第三部分:Android 应用程序接口指南---第四节:动画和图形---第一章 属性动画及动画与图形概述

    第1章 属性动画及动画与图形概述 Android提供了一系列强大的API来把动画加到UI元素中,以及绘制自定义的2D和3D图像中去.下面的几节将综述这些可用的API以及系统的功能,同时帮你做出最优的选 ...

  9. android动画具体解释二 属性动画原理

    property动画是一个强大的框架,它差点儿能使你动画不论什么东西. 你能够定义一个动画来改变对象的不论什么属性,不论其是否被绘制于屏幕之上. 一个属性动画在一定时间内多次改变一个属性(对象的一个字 ...

随机推荐

  1. (转)Tomcat目录结构

    首先来了解一下Tomcat5.5的目录结构: /bin:存放windows或Linux平台上启动和关闭Tomcat的脚本文件 /conf:存放Tomcat服务器的各种全局配置文件,其中包括server ...

  2. 配置spotlight连接linux服务器

    本文转自(https://blog.csdn.net/qq_31391261/article/details/79429098) 一.配置spotlight连接linux服务器 1.以管理员身份运行软 ...

  3. 通过no-gui模式运行jmeter脚本与生成报告

    说明:使用NO-GUI 模式,即命令行模式运行 JMeter 测试脚本能够大大缩减所需要的系统资源. 步骤:在GUI(图形化界面)模式调整好脚本,通过FTP工具将需要测试的.jmx文件传输到linux ...

  4. CISP/CISA 每日一题 21

    CISSP 每日一题(答)What is the term that identifies data ona disk after the data has supposedly been erase ...

  5. Vijos——T 1629 八

    https://vijos.org/p/1629 描述 八是个很有趣的数字啊.八=发,八八=爸爸,88=拜拜.当然最有趣的还是8用二进制表示是1000.怎么样,有趣吧.当然题目和这些都没有关系. 某个 ...

  6. l洛谷 P3926 SAC E#1 - 一道不可做题 Jelly

    P3926 SAC E#1 - 一道不可做题 Jelly 题目背景 SOL君(炉石主播)和SOL菌(完美信息教室讲师)是好朋友. 题目描述 SOL君很喜欢吃蒟蒻果冻.而SOL菌也很喜欢蒟蒻果冻. 有一 ...

  7. 题目1205:N阶楼梯上楼问题(2008年华中科技大学计算机保研机试真题:递推求解)

    题目1205:N阶楼梯上楼问题 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:2447 解决:927 题目描写叙述: N阶楼梯上楼问题:一次能够走两阶或一阶,问有多少种上楼方式. (要求 ...

  8. BZOJ 4555 [Tjoi2016&Heoi2016]求和 (多项式求逆)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4555 题目大意: 给定 \(S(n,m)\) 表示第二类斯特林数,定义函数 \(f(n ...

  9. Tomcat源代码阅读#1:classloader初始化

    Bootstrap 通过Tomcat的启动脚本能够看到启动的入口是在Bootstrap,来看下Bootstrap的main方法, /** * Main method and entry point w ...

  10. Maven在dos窗口中的命令

    转自:https://www.cnblogs.com/zyjava/p/4310957.html 1.配置环境变量 MAVEN_HOME : D:\apache-maven-3.0.2 MAVEN : ...