android动画

2种Animation模式:

1. Tween Animation补间动画:通过对场景里的对象不断做图像变换(平移、缩放、旋转)产生动画效果,即是一种渐变动画。开发者只需提供动画开始和结束的关键帧,而动画变化的中间帧则由系统计算并补齐。

2. Frame Animation:顺序播放事先做好的图像,是一种画面转换动画。由系统控制依次显示这些静态的图片,利用人眼视觉暂留,给用户造成动画的错觉

动画类型

下面先来看看Android提供的动画类型。Android的animation由四种类型组成

在XML文件中:

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

在Java 源码中定义了相应的类,可以使用这些类的方法来获取和操作相应的属性:

  • AlphaAnimation渐变透明度动画效果
  • ScaleAnimation渐变尺寸伸缩动画效果
  • TranslateAnimation画面转换位置移动动画效果
  • RotateAnimation画面转移旋转动画效果

Tween Animation

一个tween动画将对视图对象中的内容进行一系列简单的转换(位置,大小,旋转,透明性)。如果你有一个文本视图对象,你可以移动它,旋转它,让它变大或让它变小,如果文字下面还有背景图像,背景图像也会随着文件进行转换。

使用XML来定义Tween Animation

动画的XML文件在工程中res/anim目录,这个文件必须包含一个根元素,可以使<alpha><scale> <translate> <rotate>插值元素或者是把上面的元素都放入<set>元素组中,默认情况下,所以的动画指令都是同时发生的,为了让他们按序列发生,需要设置一个特殊的属性startOffset。动画的指令定义了你想要发生什么样的转换,当他们发生了,应该执行多长时间,转换可以是连续的也可以使同时的。例如,你让文本内容从左边移动到右边,然后旋转180度,或者在移动的过程中同时旋转,没个转换需要设置一些特殊的参数(开始和结束的大小尺寸的大小变化,开始和结束的旋转角度等等,也可以设置些基本的参数(例如,开始时间与周期),如果让几个转换同时发生,可以给它们设置相同的开始时间,如果按序列的话,计算开始时间加上其周期。


interpolator的解释

interpolator定义一个动画的变化率(the rate of change)。这使得基本的动画效果(alpha, scale, translate, rotate)得以加速,减速,重复等。

Interpolator 定义了动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等。Interpolator 是基类,封装了所有 Interpolator 的共同方法,它只有一个方法,即 getInterpolation (float input),该方法 maps a point on the timeline to a multiplier to be applied to the transformations of an animation。Android 提供了几个 Interpolator 子类,实现了不同的速度曲线,如下:

AccelerateDecelerateInterpolator在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator在动画开始的地方速率改变比较慢,然后开始加速
CycleInterpolator动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator在动画开始的地方速率改变比较慢,然后开始减速
LinearInterpolator在动画的以均匀的速率改变

 补间动画的<set/>元素支持一个android:interpolator属性

下面给出一个完整的XML定义:

<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>

Tween Animation如何使用

使用AnimationUtils类的静态方法loadAnimation()来加载XML中的动画XML文件

//main.xml中的ImageView
ImageView spaceshipImage = (ImageView) findViewById(R.id.spaceshipImage);
//加载动画
Animation anim =AnimationUtils.loadAnimation(this, R.anim.hyperspace_jump);
//设置动画结束后保留结束状态
anim.setFillAfter(true);
//使用ImageView显示动画
spaceshipImage.startAnimation(anim);

如何在Java代码中定义动画

//在代码中定义 动画实例对象 
private Animation myAnimation_Alpha; 
private Animation myAnimation_Translate; 

//根据各自的构造方法来初始化一个实例对象 
myAnimation_Alpha=new AlphaAnimation(0.1f, 1.0f); 
myAnimation_Translate=new TranslateAnimation(30.0f, -80.0f, 30.0f, 300.0f); 
spaceshipImage.startAnimation(anim);




Frame Animation

Frame Animation是顺序播放事先做好的图像,跟电影类似。不同于animation package, Android SDK提供了另外一个类AnimationDrawable来定义、使用Frame Animation。

Frame Animation可以在XML Resource定义(还是存放到res\anim文件夹下),也可以使用AnimationDrawable在代码中定义,先创建AnimationDrawable对象,然后调用addFrame向动画中添加帧,每调用一次,就向<animation-list.../>中添加一个item子元素。由于Tween Animation与Frame Animation有着很大的不同,因此XML定义的格式也完全不一样,其格式是:首先是animation-list根节点,animation-list根节点中包含多个item子节点,每个item节点定义一帧动画,当前帧的drawable资源和当前帧持续的时间。下面对节点的元素加以说明: 

XML属性说明
drawable当前帧引用的drawable资源
duration当前帧显示的时间(毫秒为单位)
oneshot如果为true,表示动画只播放一次停止在最后一帧上,如果设置为false表示动画循环播放。
variablePaddingIf true, allows the drawable’s padding to change based on the current state that is selected.
visible规定drawable的初始可见性,默认为flase;

下面就给个具体的XML例子,来定义一帧一帧的动画:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/rocket_thrust1" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust2" android:duration="200" />
    <item android:drawable="@drawable/rocket_thrust3" android:duration="200" />
</animation-list>

上面的XML就定义了一个Frame Animation,其包含3帧动画,3帧动画中分别应用了drawable中的3张图片:rocket_thrust1,rocket_thrust2,rocket_thrust3,每帧动画持续200毫秒。

然后我们将以上XML保存在res/anim/件夹下,命名为rocket_thrust.xml,接下来在程序中启动动画播放:

<pre name="code" class="javascript">AnimationDrawable rocketAnimation;

public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);

  ImageView rocketImage = (ImageView) findViewById(R.id.rocket_image);
  rocketImage.setBackgroundResource(R.anim.rocket_thrust);//设置rocketImage用于显示thrust动画
  rocketAnimation = (AnimationDrawable) rocketImage.getBackground();//获取动画对象
}

public boolean onTouchEvent(MotionEvent event) {
  if (event.getAction() == MotionEvent.ACTION_DOWN) {
    rocketAnimation.start();
    return true;
  }
  return super.onTouchEvent(event);
}
 
 

代码运行的结果:3张图片按照顺序的播放一次.

有一点需要强调的是:启动Frame Animation动画的代码rocketAnimation.start();不能在OnCreate()中,因为在OnCreate()中AnimationDrawable还没有完全的与ImageView绑定,在OnCreate()中启动动画,就只能看到第一张图片。这里实在拖曳事件中实现的。

逐帧动画和补间动画的结合:蝴蝶飞舞

蝴蝶的横向和上下移动---补间动画,蝴蝶的振翅效果---逐帧动画

public class ButterflyActivity extends AppCompatActivity {
    //记录image的当前位置
    private float curX=0;
    private float curY=0;
    //记录image的下一个位置
    float nextX=0;
    float nextY=0;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_butterfly);

        final ImageView imageView= (ImageView) findViewById(R.id.iv_butterfly);
        
        final Handler handler=new Handler(){
            @Override
            public void handleMessage(Message msg) {
                if (msg.what==0x123){
                    //横向一直向右飞
                    if (nextX>320){
                        curX=0;
                        nextX=0;
                    }else{
                        nextX+=8;
                    }
                    //纵向上随机上下飞
                    nextY=  curY+ (float) (Math.random()*10-5);//随机数范围为-5~5
                    TranslateAnimation anim=new TranslateAnimation(curX,nextX,curY,nextY);
                    curX=nextX;
                    curY=nextY;
                    anim.setDuration(200);
                    imageView.startAnimation(anim);
                }
            }
        };

        final AnimationDrawable drawable= (AnimationDrawable) imageView.getBackground();
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                drawable.start();
                new Timer().schedule(new TimerTask() {  //通过定时器控制TranslateAnimation
                    @Override
                    public void run() {
                        handler.sendEmptyMessage(0x123);
                    }
                },0,200);
            }
        });
    }
}



属性动画:

属性(Property)动画:安卓提供的众多动画中的一种,从某种角度来看,属性动画实际上是增强版的补间(Tween)动画。

属性动画主要由两方面组成:

1.计算各帧的相关属性值。 
2.给指定的对象设置相关的属性值。

区别:

1.补间(Tween)动画只能够操控各种组件的透明度(alpha),位置(translate),旋转(rotate)和放缩(scale)四种属性进行相应的变换,但是属性(Property)动画可以对任何的属性值做出改变。

2.补间(Tween)动画只能对UI组件作用,但是属性(Property)动画没有限制,可以对任何对象进行操作(即使没有在UI界面上绘制出来)。

属性动画API:

1.ValueAnimator:属性动画主要的时间引擎,它负责计算各个帧的属性值,也就是属性动画第一组成部分。由于ValueAnimator只会负责第一部分,第二部分给组件赋属性值就需要手动完成。

2.ObjectAnimator:ValueAnimator的子类,在使用的时候可以直接指定组件对象,使用起来更加的方便了。但是在某些场景下,ObjectAnimator存在一些限制,可能需要考虑使用ValueAnimator。

3.AnimatorSet:Animator的子类,可以用于组合多个Animator对象,还可以指定是按次序播放还是同时播放。

在ValueAnimator中还用到了一个计算工具类Evaluator(计算器),控制者属性动画如何计算属性值。Android提供了集中Evaluator:

1.IntEvaluator:用于计算int类型的属性值计算器。2.FloatEvaluator:用于计算float类型的属性值计算器。3.ArgbEvaluator:用于计算十六进制的rgb颜色值。4.TypeEvaluator:计算器的接口,供自定义计算器实现。

使用ValueAnimator创建动画大致如下四个步骤:

1.调用ValueAnimator的ofInt(), ofFloat(), ofObject()静态方法创建ValueAnimator实例,很明显这几个不同的方法创建的不同实例中,所用到的计算器也是不同的。

2.调用ValueAnimator的setDuration()等方法给属性动画设置相应的参数,如动画的持续时间,重复次数等。

3.调用start()方法启动相应的动画。

4.为ValueAnimator注册AnimatorUpdateListener监听器,在监听器中可以实时获取到ValueAnimator计算出来的属性值,只需要在监听器中赋值给对应对象就行了。
ValueAnimator animation = ValueAnimator.ofFloat(1f, 0f);//值从1到0变化
animation.setDuration(3000);
animation.setRepeatCount(1);
animation.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//使用的时候可以通过getAnimatedValue()来获取当前计算出来的帧的属性值,并赋值给制定对象。
view.invalidate();
}
});
如果是希望使用自己利用TypeEvaluator定义出来的属性值计算器,则将第一步改为:
ValueAnimator animation = ValueAnimator.ofObject( new MyTypeEvaluator(), 1f , 0f );


2.使用ObjectAnimator创建动画和ValueAnimator差不多,因为ObjectAnimator继承自ValueAnimator,所以可以直接将ValueAnimator在动画过程中计算出来的值应用到指定对象的指定属性上(ValueAnimator则需要注册一个监听器来完成此工作)。只不过ObjectAnimator已经实现了将计算结果赋值给对象,我们在使用的时候提供控件对象,不需要注册AnimatorUpdateListener监听器(没有上述的第四个步骤)。

ObjectAnimator animation = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f);
animation.setDuration(1000);
animation.setRepeatCount(1);
animation.start();

注意:
1.一定要为该对象的属性提供setter方法,如上例中要为imageView对象提供setAlpha(float value)方法;

2.在使用ObjectAnimator的对象上一定要有改变的属性值,例如上述的例子中imageView一定要有alpha这个属性值。
3.如果在第一句话是

<span style="background-color: transparent; color: inherit; white-space: pre; font-size: 12px;">少提供了一个参数,则提供的值会被认为是属性计算的结束值,对alpha这个属性一定要提供getter方法,返回的值将作为属性计算的初始值,也就是从该组件的当前状态开始执行动画。</span>

4.如果动画的对象是View,为了能显示动画的效果,需要不断的通知组件重新绘制,调用View.invalidate()方法。但是View定义的setter方法,如setAloha()等方法都会自动的调用invalidate()方法,不需要我们再额外的调用了。


ObjectAnimator实现动画

之所以选择ObjectAnimator为第一个~~是因为,这个实现最简单~~一行代码,秒秒钟实现动画,下面看个例子:
布局文件:

[html]  view plain copy
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:id="@+id/id_container" >  
  6.   
  7.     <ImageView  
  8.         android:id="@+id/id_ball"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:layout_centerInParent="true"  
  12.         android:src="@drawable/mv"   
  13.         android:scaleType="centerCrop"  
  14.         android:onClick="rotateyAnimRun"  
  15.         />  
  16.   
  17. </RelativeLayout>  
很简单,就一张妹子图片~
Activity代码:

[java]  view plain copy
  
  1. public class ObjectAnimActivity extends Activity  
  2. {  
  3.     @Override  
  4.     protected void onCreate(Bundle savedInstanceState)  
  5.     {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(R.layout.xml_for_anim);  
  8.     }  
  9.   
  10.     public void rotateyAnimRun(View view)  
  11.     {  
  12.          ObjectAnimator//  
  13.          .ofFloat(view, "rotationX"0.0F, 360.0F)//  
  14.          .setDuration(500)//  
  15.          .start();  
  16.     }  
  17. }  
效果:

是不是一行代码就能实现简单的动画~~

对于ObjectAnimator

1、提供了ofInt、ofFloat、ofObject,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。

当对于属性值,只设置一个的时候,会认为当然对象该属性的值为开始(getPropName反射获取),然后设置的值为终点。如果设置两个,则一个为开始、一个为结束~~~

动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新某个属性,必须得有getter(设置一个属性值的时候)和setter方法~

2、如果你操作对象的该属性方法里面,比如上例的setRotationX如果内部没有调用view的重绘,则你需要自己按照下面方式手动调用。

[java]  view plain copy
  1. anim.addUpdateListener(new AnimatorUpdateListener()  
  2.         {  
  3.             @Override  
  4.             public void onAnimationUpdate(ValueAnimator animation)  
  5.             {  
  6. //              view.postInvalidate();  
  7. //              view.invalidate();  
  8.             }  
  9.         });  
3、看了上面的例子,因为设置的操作的属性只有一个,那么如果我希望一个动画能够让View既可以缩小、又能够淡出(3个属性scaleX,scaleY,alpha),只使用ObjectAnimator咋弄?

想法是不是很不错,可能会说使用AnimatorSet啊,这一看就是一堆动画塞一起执行,但是我偏偏要用一个ObjectAnimator实例实现呢~下面看代码:

[java]  view plain copy
  1. public void rotateyAnimRun(final View view)  
  2. {  
  3.     ObjectAnimator anim = ObjectAnimator//  
  4.             .ofFloat(view, "zhy"1.0F,  0.0F)//  
  5.             .setDuration(500);//  
  6.     anim.start();  
  7.     anim.addUpdateListener(new AnimatorUpdateListener()  
  8.     {  
  9.         @Override  
  10.         public void onAnimationUpdate(ValueAnimator animation)  
  11.         {  
  12.             float cVal = (Float) animation.getAnimatedValue();  
  13.             view.setAlpha(cVal);  
  14.             view.setScaleX(cVal);  
  15.             view.setScaleY(cVal);  
  16.         }  
  17.     });  
  18. }  
把设置属性的那个字符串,随便写一个该对象没有的属性,就是不管~~咱们只需要它按照时间插值和持续时间计算的那个值,我们自己手动调用~

效果:

这个例子就是想说明一下,有时候换个思路不要被API所约束,利用部分API提供的功能也能实现好玩的效果~~~

比如:你想实现抛物线的效果,水平方向100px/s,垂直方向加速度200px/s*s ,咋实现呢~~可以自己用ObjectAnimator试试~

4、其实还有更简单的方式,实现一个动画更改多个效果:使用propertyValuesHolder

[java]  view plain copy
  1. public void propertyValuesHolder(View view)  
  2.     {  
  3.         PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,  
  4.                 0f, 1f);  
  5.         PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 
  6.                 0, 1f);  
  7.         PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 
  8.                 0, 1f);  
  9.         ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();  
  10.     }  

 4、ValueAnimator实现动画

和ObjectAnimator用法很类似,简单看一下用view垂直移动的动画代码:

[java]  view plain copy
  1. public void verticalRun(View view)  
  2.     {  
  3.         ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight  
  4.                 - mBlueBall.getHeight());  
  5.         animator.setTarget(mBlueBall);  
  6.         animator.setDuration(1000).start();  
  7.     }  
给你的感觉是不是,坑爹啊,这和ObjectAnimator有毛线区别~但是仔细看,你看会发现,没有设置操作的属性~~也就是说,上述代码是没有任何效果的,没有指定属性~

这就是和ObjectAnimator的区别之处:ValueAnimator并没有在属性上做操作,你可能会问这样有啥好处?我岂不是还得手动设置?

好处:不需要操作的对象的属性一定要有getter和setter方法,你可以自己根据当前动画的计算值,来操作任何属性,记得上例的那个【我希望一个动画能够让View既可以缩小、又能够淡出(3个属性scaleX,scaleY,alpha)】吗?其实就是这么个用法~

实例:

我们先看一个自由落体的代码:

[java]  view plain copy
  1. /** 
  2.      * 自由落体 
  3.      * @param view 
  4.      */  
  5.     public void verticalRun( View view)  
  6.     {  
  7.         ValueAnimator animator = ValueAnimator.ofFloat(0, mScreenHeight  
  8.                 - mBlueBall.getHeight());  
  9.         animator.setTarget(mBlueBall);  
  10.         animator.setDuration(1000).start();  
  11. //      animator.setInterpolator(value)  
  12.         animator.addUpdateListener(new AnimatorUpdateListener()  
  13.         {  
  14.             @Override  
  15.             public void onAnimationUpdate(ValueAnimator animation)  
  16.             {  
  17.                 mBlueBall.setTranslationY((Float) animation.getAnimatedValue());  
  18.             }  
  19.         });  
  20.     }  
与ObjectAnimator不同的就是我们自己设置元素属性的更新~虽然多了几行代码,但是貌似提高灵活性~


5、监听动画的事件

对于动画,一般都是一些辅助效果,比如我要删除个元素,我可能希望是个淡出的效果,但是最终还是要删掉,并不是你透明度没有了,还占着位置,所以我们需要知道动画如何结束。

所以我们可以添加一个动画的监听:

[java]  view plain copy
  1. public void fadeOut(View view)  
  2.     {  
  3.         ObjectAnimator anim = ObjectAnimator.ofFloat(mBlueBall, "alpha"0.5f);
  4.         anim.addListener(new AnimatorListener()  
  5.         {  
  6.             @Override  
  7.             public void onAnimationStart(Animator animation)  
  8.             {  
  9.                 Log.e(TAG, "onAnimationStart");  
  10.             }  
  11.   
  12.             @Override  
  13.             public void onAnimationRepeat(Animator animation)  
  14.             {  
  15.                 // TODO Auto-generated method stub  
  16.                 Log.e(TAG, "onAnimationRepeat");  
  17.             }  
  18.   
  19.             @Override  
  20.             public void onAnimationEnd(Animator animation)  
  21.             {  
  22.                 Log.e(TAG, "onAnimationEnd");  
  23.                 ViewGroup parent = (ViewGroup) mBlueBall.getParent();  
  24.                 if (parent != null)  
  25.                     parent.removeView(mBlueBall);  
  26.             }  
  27.   
  28.             @Override  
  29.             public void onAnimationCancel(Animator animation)  
  30.             {  
  31.                 // TODO Auto-generated method stub  
  32.                 Log.e(TAG, "onAnimationCancel");  
  33.             }  
  34.         });  
  35.         anim.start();  
  36.     }  
这样就可以监听动画的开始、结束、被取消、重复等事件~但是有时候会觉得,我只要知道结束就行了,这么长的代码我不能接收,那你可以使用AnimatorListenerAdapter

[java]  view plain copy
  1. anim.addListener(new AnimatorListenerAdapter()  
  2. {  
  3.     @Override  
  4.     public void onAnimationEnd(Animator animation)  
  5.     {  
  6.         Log.e(TAG, "onAnimationEnd");  
  7.         ViewGroup parent = (ViewGroup) mBlueBall.getParent();  
  8.         if (parent != null)  
  9.             parent.removeView(mBlueBall);  
  10.     }  
  11. });  

AnimatorListenerAdapter继承了AnimatorListener接口,然后空实现了所有的方法~

animator还有cancel()和end()方法:cancel动画立即停止,停在当前的位置;end动画直接到最终状态。微笑

1、如何使用xml文件来创建属性动画

大家肯定都清楚,View Animator 、Drawable Animator都可以在animator文件夹下创建动画,然后在程序中使用,甚至在Theme中设置为属性值。当然了,属性动画其实也可以在文件中声明:

首先在res下建立animator文件夹,然后建立res/animator/scalex.xml

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:duration="1000"  
  4.     android:propertyName="scaleX"  
  5.     android:valueFrom="1.0"  
  6.     android:valueTo="2.0"  
  7.     android:valueType="floatType" >  
  8. </objectAnimator>  
代码:

[java]  view plain copy
  1. public void scaleX(View view)  
  2.     {  
  3.         // 加载动画  
  4.         Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex);  
  5.         anim.setTarget(mMv);  
  6.         anim.start();  
  7.     }  
使用AnimatorInflater加载动画的资源文件,然后设置目标,就ok~~是不是很简单,这只是单纯横向的放大一倍~

如果我希望纵向与横向同时缩放呢?则可以怎么定义属性文件:

[html]  view plain copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <set xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:ordering="together" >  
  4.   
  5.     <objectAnimator  
  6.         android:duration="1000"  
  7.         android:propertyName="scaleX"  
  8.         android:valueFrom="1"  
  9.         android:valueTo="0.5" >  
  10.     </objectAnimator>  
  11.     <objectAnimator  
  12.         android:duration="1000"  
  13.         android:propertyName="scaleY"  
  14.         android:valueFrom="1"  
  15.         android:valueTo="0.5" >  
  16.     </objectAnimator>  
  17.   
  18. </set>  
使用set标签,有一个orderring属性设置为together,【还有另一个值:sequentially(表示一个接一个执行)】。

上篇博客中忽略了一个效果,就是缩放、反转等都有中心点或者轴,默认中心缩放,和中间对称线为反转线,所以我决定这个横向,纵向缩小以左上角为中心点:

代码:

[java]  view plain copy
  1. // 加载动画  
  2.         Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale);  
  3.         mMv.setPivotX(0);  
  4.         mMv.setPivotY(0);  
  5.         //显示的调用invalidate  
  6.         mMv.invalidate();  
  7.         anim.setTarget(mMv);  
  8.         anim.start();  
很简单,直接给View设置pivotX和pivotY,然后调用一下invalidate,就ok了。







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值