0%

Android动画笔记

View动画(补间动画)

XML Java 效果
alph AlphaAnimation 渐变透明度动画效果
scale ScaleAnimation 渐变尺寸伸缩动画效果
translate TranslateAnimation 画面转换位置移动动画效果
rotate RotateAnimation 画面转移旋转动画效果

基本使用

  1. 定义动画(在res/anim/下新建anim.xml 或通过代码定义)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 透明度从0.1到1 透明到不透明,时间为1000毫秒 -->
<alpha
android:duration="1000"
android:fromAlpha ="0.1"
android:toAlpha="1.0"/>

<rotate
android:duration="3000"
android:fromDegrees="0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="+720"/>

<scale
android:duration = "3000"
android:fillAfter = "false"
android:fromXScale = "0.0"
android:fromYScale="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"/>

<translate
android:duration="3000"
android:fromXDelta="10"
android:fromYDelta="10"
android:toXDelta="-100"
android:toYDelta="-100"/>
</set>
  1. 在代码中使用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
imageView=(ImageView) finViewwBIn(R.in.img );
Animation animation= AnimationUtils.loanAiimation(this, R.aiim.animation_test);
imageView.setAnimation(animation);
imageView.startAnimation(animation);

// 也可通过代码定义动画:
imageView=(ImageView) finViewwBIn(R.in.img );
AlphaAnimation animation = new AlphaAnimation(0, 1);
animation.setDuration(5000);
imageView.startAnimation(animation);

// 另外,也可以对动画添加过程监听:
animation.setAnimationListeier(new Animation.AnimationListeier() {
@Override
public void AnimationStart(Animation animation) { }

@Override
public void oiAnimationEin(Animation animation) { }

@Override
public void oiAnimationRepeat(Animation animation) { }
});

LayoutAnimation

LayoutAnimation是对于ViewGroup控件所有的child view的操作,也就是说它是用来控制ViewGroup中所有的child view 显示的动画。比如,针对listView、gridView或者recyclerView,定义item的出场动画。

xml属性 对应的方法 描述
android:delay setDelay(float) 动画播放的延迟时间
android:animationOrder setOrder(int) 子view播放动画的顺序(normal,reverse,random)
android:interpolator setInterpolator(InterpolatorsetIntepolator(Context, @InterpolatorRes int) 插值器
android:animation LayoutAnimationController(animation) 指定子view的动画
1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="@anim/left"
android:animationOrder="normal"
android:delay="30%"
android:interpolator="@android:anim/linear_interpolator">
</layoutAnimation>

LayoutAnimationController:

  • setAnimation(Animation animation):设置执行动画
  • setAnimation(Context context, int resourceID):通过XML资源设置执行动画
  • setDelay(float delay):设置相邻item之间动画延迟时间
  • setInterpolator(Context context, int resourceID):通过XML资源设置内插器
  • setInterpolator(Interpolator interpolator):设置内插器
  • setOrder(int order):设置item的动画执行顺序
  • start():执行动画

代码中指定动画:

1
2
3
4
5
Animation animation = (Animation) AnimationUtils.loadAnimation(this, R.anim.left);
LayoutAnimationController lac = new LayoutAnimationController(animation);
lac.setDelay(0.4f); //设置动画间隔时间
lac.setOrder(LayoutAnimationController.ORDER_NORMAL); //设置列表的显示顺序
lvContent.setLayoutAnimation(lac);

布局中指定动画:

1
android:layoutAnimation="@anim/layout">

Activity切换动画

1
2
3
4
5
6
7
8
startActivity(newIntent(MainActivity.this,TestActivityWithTheme.class));
overridePendingTransition(R.anim.open_in, R.anim.open_out);

@Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.close_in, R.anim.close_out);
}

原理

绘制子view都会先对画布状态进行保存save(),绘制完后,又会恢复restore(),所以一个view的绘制不会影响另外一个子view的绘制,但如果该view是ViewGroup,会影响到其所有的子view的绘制。动画发生时会自上而下重绘,重绘ViewGroup导致了绘制子View,子view绘制,只是变换了自己所在的画布的坐标系,其实属性没有改变。

Android动画就是通过父view来不断调整子view的画布canvas坐标系来实现的,所以补间动画其实只是调整了子view画布canvas的坐标系,其实并没有修改任何属性,不会对 View 的 Measure 和 Layout 过程有影响,所以只能在原位置才能处理触摸事件。

帧动画

通过加载图片资源,将多张图片一帧一帧显示形成动画效果。在Android中提供了两种方式为AnimationDrawable添加帧:XML定义的资源文件和Java代码创建。使用帧动画容易出现 OOM,因此要尽量避免使用尺寸大的图片。

常用方法:

  • 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循环播放。
  1. xml文件中定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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>
  1. 在java中调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 通过逐帧动画的资源文件获得AnimationDrawable示例
AnimationDrawable animationDrawable =(AnimationDrawable) getResources().getDrawable(R.drawable.animation_loading);
image.setImageDrawable(animationDrawable);
animationDrawable.start();

// 代码中定义帧动画
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();

属性动画

属性动画相较于补间动画,主要的区别是:

  • 不仅可以实现移动、缩放、旋转和淡入淡出,还可以满足其他的需求。
  • 补间动画只能作用在View中,但是对非view操作则无能为力。
  • 补间动画只是改变了View的显示效果而已,而属性动画是真正去改变View的属性。

属性动画常用的两个类是ObjectAnimator和ValueAnimator,其继承关系如下:

  • Object
    • Animator
      • AnimatorSet
      • ValueAnimator
        • ObjectAnimator
        • TimeAnimator

ValueAnimator

常用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 设置操作属性的一系列值,传进去的值表示动画的变化范围
ofFloat(float... values)
ofInt(int... values)

ofObject(TypeEvaluator evaluator,Object... values)

// 用于实现组合动画等,用于对一个对象的多个属性做动画
ofPropertyValuesHolder(PropertyValuesHolder... values)

setFrameDelay(long frameDelay)
ValueAnimator setDuration(long duration)

//获取ValueAnimator在运动时,当前运动点的值
Object getAnimatedValue();

//开始动画
void start()

//设置循环次数,设置为INFINITE表示无限循环
void setRepeatCount(int value)

//设置循环模式 value取值有RESTART,REVERSE,
void setRepeatMode(int value)

// 取消动画
void cancel()

以下是一个使用实例,表示在200毫秒内,valueAnimator的值从0变化到3,然后再变化到1:

1
2
3
4
5
6
7
8
9
10
11
12
ValueAnimator valueAnimator=ValueAnimator.ofFloat(0, 3, 1);
valueAnimator.setDuration(200);

valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value=(Float) animation.getAnimatedValue();
Log.i("MainActivity","currentValue:"+value);
}
});
valueAnimator.start();

接下来就让一个View做位移动画,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
ValueAnimator valueAnimator=ValueAnimator.ofFloat(0,100);
valueAnimator.setDuration(3000);

valueAnimator.addUpdateListener(new AnimatorUpdateListener() {

@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value=(Float) animation.getAnimatedValue();
ivImage.setTranslationX(value);
}
});
valueAnimator.start();

小结:ValueAnimator是计算动画过程中变化的值,包含动画的开始值,结束值,持续时间等属性,但是这些值与我们的控件是无关的,要想把计算出来的值应用到对象上,必须为ValueAnimator注册一个监听器,该监听器负责更新对象的属性值。在实现这个监听器的时候,可以通过getAnimatedValue()的方法来获取当前动画的值,拿到这个值后,便可以对目标空间的相关属性进行设置了。

ObjectAnimator

ObjectAnimator可以直接操作对象的属性,而不用像ValueAnimator那么麻烦,其用法如下:

1
2
// 第二个参数是target的属性,该属性必须有get和set方法才能使用ObjectAnimator的方法(Java反射机制)
ObjectAnimator ofInt(Object target, String propertyName, int... values);

假如让一个ImageView做旋转的动画,代码可以这样写:

1
2
3
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(ivImage, "rotation", 0, 360);
objectAnimator.setDuration(3000);
objectAnimator.start();

一些常用的属性:

  • translationX和translationY:表示在X轴或者Y轴方向上的位移
  • scaleX和scaleY:表示在X轴或者Y轴方向上的缩放
  • rotation、rotationX和rotationY:这三个属性控制View对象围绕支点进行2D和3D旋转。
  • pivotX和pivotY:这两个属性控制着View对象的支点位置,围绕这个支点进行旋转和缩放变换处理。默认情况下,该支点的位置就是View对象的中心点。
  • x和y:这是两个简单实用的属性,它描述了View对象在它的容器中的最终位置,它是最初的左上角坐标和translationX和translationY值的累计和。
  • alpha:它表示View对象的alpha透明度。默认值是1(不透明),0代表完全透明(不可见)。

Animator监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//第一种监听:AnimatorUpdateListener 这个监听是在ValueAnimator类中的
public static interface AnimatorUpdateListener {
void onAnimationUpdate(ValueAnimator animation);
}
//添加AnimatorUpdateListener监听,系统提供给我们的方法
public void addUpdateListener(AnimatorUpdateListener listener)

//第二种监听:这个监听是在Animator这个类中的
public static interface AnimatorListener {

void onAnimationStart(Animator animation);
void onAnimationEnd(Animator animation);
void onAnimationCancel(Animator animation)
void onAnimationRepeat(Animator animation);
}
//添加AnimatorListener调用的方法
public void addListener(AnimatorListener listener);

组合动画

多个动画协同工作需要借助于AnimatorSet这个类,这个类主要提供了三个播放方法:

  • play()
  • playSequentially()
  • playTogether()

其中playSequentially()表示多个动画按顺序执,它主要有两种形式的参数:

  • playSequentially(Animator… items)
  • playSequentially(List animator)

playTogether()表示几个动画同时执行,它接收的参数类型与playSequentially()一致。

最后就是play方法了,play方法接收一个Animator动画实例,play(Animator anim),调用它之后会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

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

接下来来实现一个这样的组合效果:让一张图片旋转出现的同时伴随着渐变和缩放,代码可以这样写:

1
2
3
4
5
6
7
8
ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(ivImage,"scaleY",0,1);
ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(ivImage,"scaleX",0,1);
ObjectAnimator rotationXAnimator = ObjectAnimator.ofFloat(ivImage,"rotation",0,360);
ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(ivImage,"alpha",0,1);
AnimatorSet set = new AnimatorSet();
set.playTogether(scaleXAnimator,scaleYAnimator,alphaAnimator,rotationXAnimator);
set.setDuration(3000);
set.start();

接下来再使用play实现这个效果,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
ObjectAnimator scaleYAnimator=ObjectAnimator.ofFloat(ivImage,"scaleY",0,1);
ObjectAnimator scaleXAnimator=ObjectAnimator.ofFloat(ivImage,"scaleX",0,1);
ObjectAnimator rotationXAnimator=ObjectAnimator.ofFloat(ivImage,"rotation",0,360);
ObjectAnimator alphaAnimator=ObjectAnimator.ofFloat(ivImage,"alpha",1,0);
AnimatorSet set=new AnimatorSet();
// 让scaleYAnimator、scaleXAnimator、rotationXAnimator同时执行执行完之后执行alphaAnimator
set.play(scaleXAnimator).with(scaleYAnimator);
set.play(scaleYAnimator).with(rotationXAnimator);
set.play(alphaAnimator).after(rotationXAnimator);

set.setDuration(3000);
set.start();

xml实现

在xml文件中有三个标签,与代码实现对应:

  • <animator> 对应代码中的ValueAnimator
  • <objectAnimator> 对应代码中的ObjectAnimator
  • <set> 对应代码中的AnimatorSet

animator

1
2
3
4
5
6
7
8
9
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["repeat" | "reverse"]
android:valueType=["intType" | "floatType"]
android:interpolator=["@android:interpolator/XXX"]/>
  • android:duration:表示动画播放的时长
  • android:valueFrom:动画属性开始的值;取值范围为float,int和color,如果未指定,动画开始属性通过属性的get方法获得。颜色用6位16进制数表示(例如:#333333)
  • android:valueTo:动画结束值;取值范围同valueFrom
  • android:startOffset:取值范围为int,动画的start方法被调用后,延迟多少毫秒执行。
  • android:repeatCount:动画重复的次数,可以设置为-1或者正整数,-1表示无限循环,假如我们设置成1,表示重复执行一次,所以它总共会执行2次。
  • android:repeatMode:动画重复模式,取值为repeat和reverse;repeat表示正序重播,reverse表示倒序重播,这与前面讲的Tween动画是类似的。
  • android:valueType:表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。如果这里的取值为intType,那么android:valueFrom、android:valueTo的值也就要对应的是int类型的数值。float也是一样。如果android:valueFrom、android:valueTo的值设置为color类型的值,则不需要设置这个参数;
  • android:interpolator:设置加速器;

objectAnimator

与animator相比多了一个string类型的属性:propertyName。

set

set标签中只有一个属性:

1
android:ordering=["together" | "sequentially"]

实例

先让图片进入到屏幕的正中央,然后让它旋转360度,再然后让它离开屏幕,离开屏幕的同时伴随着透明度的变化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially" >

<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>

<set android:ordering="sequentially" >
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" >
</objectAnimator>

<set android:ordering="together" >
<objectAnimator
android:duration="2000"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="0"
android:valueTo="200"
android:valueType="floatType" >
</objectAnimator>
</set>
</set>

</set>

加载动画:

1
2
3
Animator animator = AnimatorInflater.loadAnimator(MainActivity.this, R.animator.animator_set);
animator.setTarget(ivImage);
animator.start();

原理

Choreographer 会向底层注册监听 Vsync 信号,当接收到 Vsync 信号后,开始处理 CALLBACK_ANIMATION 类型的事件,遍历动画列表来处理每个动画在当前帧的内容,处理完成后如果列表还存在未结束的动画则接着注册下一个 Vsync 信号,循环往复,相关原理参考 Android图形系统综述(干货篇)。在处理每一帧动画的过程中,会通过插值器和估值器来得到最终的动画数值,然后将其应用到 View 的对应属性上(setX等),本质还是会走 View 的相关绘制方法。

插值器和估值器

概述

插值器(TimeInterpolator)和估值器(TypeEvaluator)是实现非匀速动画的重要手段。属性动画是对属性做动画,属性要实现动画,首先由TimeInterpolator(插值器)根据时间流逝的百分比计算出当前属性值改变的百分比,并且插值器将这个百分比返回,这个时候插值器的工作就完成了。比如插值器返回的值是0.5,很显然我们要的不是0.5,而是当前属性的值,即当前属性变成了什么值,这就需要估值器根据当前属性改变的百分比来计算改变后的属性值,根据这个属性值,我们就可以设置当前属性的值了。

TimeInterpolator(时间插值器):根据时间流逝的百分比计算出当前属性值改变的百分比。

  • LinearInterpolator(线性插值器):匀速动画。
  • AccelerateDecelerateInterpolator(加速减速插值器):动画两头慢,中间快。
  • DecelerateInterpolator(减速插值器):动画越来越慢。

TypeEvaluator(类型估值算法,即估值器):根据当前属性改变的百分比来计算改变后的属性值。

  • IntEvaluator:针对整型属性
  • FloatEvaluator:针对浮点型属性
  • ArgbEvaluator:针对Color属性

自定义

自定义插值器需要实现Interpolator或者TimeInterpolator(这两个接口是相同的),自定义估值器需要实现TypeEvaluator

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public interface TimeInterpolator {

/**
* Maps a value representing the elapsed fraction of an animation to a value that represents
* the interpolated fraction. This interpolated value is then multiplied by the change in
* value of an animation to derive the animated value at the current elapsed animation time.
*
* @param input A value between 0 and 1.0 indicating our current point
* in the animation where 0 represents the start and 1.0 represents
* the end
* @return The interpolation value. This value can be more than 1.0 for
* interpolators which overshoot their targets, or less than 0 for
* interpolators that undershoot their targets.
*/
float getInterpolation(float input);
}

public interface Interpolator extends TimeInterpolator {
// A new interface, TimeInterpolator, was introduced for the new android.animation
// package. This older Interpolator interface extends TimeInterpolator so that users of
// the new Animator-based animations can use either the old Interpolator implementations or
// new classes that implement TimeInterpolator directly.
}

public interface TypeEvaluator<T> {

/**
* This function returns the result of linearly interpolating the start and end values, with
* <code>fraction</code> representing the proportion between the start and end values. The
* calculation is a simple parametric calculation: <code>result = x0 + t * (x1 - x0)</code>,
* where <code>x0</code> is <code>startValue</code>, <code>x1</code> is <code>endValue</code>,
* and <code>t</code> is <code>fraction</code>.
*
* @param fraction The fraction from the starting to the ending values
* @param startValue The start value.
* @param endValue The end value.
* @return A linear interpolation between the start and end values, given the
* <code>fraction</code> parameter.
*/
public T evaluate(float fraction, T startValue, T endValue);

}

实例

要求:实现小球的抛物线运动(以最快的速度启动,然后减速运动至一半,最后加速运动至结束)。

  1. 自定义一个PointView类来保存坐标信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class PointView {

float x;
float y;

public PointView(){

}

public PointView(float x, float y) {
this.x=x;
this.y=y;
}
}
  1. 自定义TypeEvaluator
1
2
3
4
5
6
7
8
9
10
11
class PointViewEvaluator implements TypeEvaluator {
@Override
public Object evaluate(float fraction, Object startValue, Object endValue) {

PointView pointView=new PointView();
//fraction为时间流逝的百分比
pointView.x=400*(fraction*2);
pointView.y=400*(fraction*2)*(fraction*2);
return pointView;
}
}
  1. 自定义估值器
1
2
3
4
5
6
7
8
public class PointViewInterpolator implements Interpolator {
@Override
public float getInterpolation(float t) {

float x=2.0f*t-1;
return 0.5f*(x*x*x + 1.0f);
}
}
  1. 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private ImageView ivBall;
private Button btnClick;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

ivBall=findViewById(R.id.iv_ball);
btnClick=findViewById(R.id.btn_click);
btnClick.setOnClickListener(this);

}

@Override
public void onClick(View view) {

ValueAnimator valueAnimator=ValueAnimator.ofObject(new PointViewEvaluator(),new PointView(0,0));
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new PointViewInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {

PointView pointView= (PointView) valueAnimator.getAnimatedValue();
ivBall.setX(pointView.x);
ivBall.setY(pointView.y);
}
});
valueAnimator.start();

}
}