Android之动画(Java代码实现)2
文章链接:Android之动画(Java代码实现)2
相关链接: Android之动画(Java代码实现)1
知识点:
概述
- ValueAnimator的ofInt()/ofFloat()/ofArgb()构造方法详解和使用;
- ObjectAnimator动画类详解和使用;
- AnimatorSet类集合类详解和使用;
- 自定义速率;
- 新名词记录{自定义速率:TimeInterpolator;AnimatorSet:动画的集合控制类;ObjectAnimator:可以定义动作方法的类;Animator:动作基类;}
概述
Animator作为Android四大补间动画基类,我在上一篇文章已经讲了,请戳这里 Android之动画(Java代码实现)1。后来一看,继承此基类的类还有不少,比如ValueAnimator,ObjectAnimator,AnimatorSet等等,他们其实都是来做动画的。
下面将一一来讲解这几个类的效果和用法。
ValueAnimator动画类
前方高能,绑好安全带
前方高能,绑好安全带
前方高能,绑好安全带
先来一个重点分析:ValueAnimator的静态构造函数一共有3个,分别是ofInt(),.ofFloat().ofArgb()三个,如何来理解呢?很简单,三个函数都是传入不限制个参数,拿ofInt()来说,例如我们传入ofInt(0, 400),然后我们设置执行时间setDuration(3000),那么他就是在3000毫秒之内走0–400间隔,步进就是400/3000(距离/时间)。到这里应该可以理解了吧,通俗来讲,就是我们给他一个“距离”,希望这个动画在setDuration(时间)的时间内走完。.ofFloat().ofArgb()同理可得,一个是帮我们走float类型和argb颜色类型。系不系很简单。
那么问题就来了,我们让API帮我们走过这个距离,那这个是要干嘛用啊?
因为是我叫你帮我计算的嘛,所以我希望可以把每走一步的值,都给回我,让我自己去根据这些值进行相应的操作。嗯呢,这是个好的想法。实际上Google也是这样想的。我计算了步进值,并走完,但是我不能帮你实现神马功能啊,只能教会给你咯。所以Google的API提供了一个回调函数ValueAnimator.AnimatorUpdateListener()。只要实现这个函数,然后设置给动画的执行者,那么我就可以将值回传给你了。
那么这个ValueAnimator动画执行者的3个函数大概就是这么回事。现在理解起来系不系很简单了?!
当然,执行者还有其他的属性可以设置,比如是否重复,重复的次数,计算的速率是加速/减速还是其他等等,都是可以调用相应方法进行设置的。
下面一个方法,是获取屏幕的宽度,然后使得要“动画的值”在0至屏幕宽度之间进行计算,并且是reverse的。然后我们在回调函数里头进行的设置就是设置图片的左边距,使得“从左到右,再从右到左”进行无限循环滚动。
高能区结束
高能区结束
高能区结束
下面看代码。
void valueAnimationTest() {
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
int width = metric.widthPixels; // 屏幕宽度(像素)
/**
* 意思就是:从0--400,走的都是float类型的数值,步进为((400-0)/3000)pix/ms
*/
//1.调用ofInt(int...values)方法创建ValueAnimator对象
// ValueAnimator valueAnimator = ValueAnimator.ofInt(0, width - imgV_animator.getWidth());
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, width - imgV_animator.getWidth());
valueAnimator.setDuration(3000); //设置动画的时间
valueAnimator.setInterpolator(new AccelerateInterpolator()); //设置为加速
//给动画添加更新的监听
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//获取到上面从0--屏幕宽度之间执行的值,步进为400/3000/ms
float animatorValue = (float) animation.getAnimatedValue();
//获取到imageview的布局参数
ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) imgV_animator.getLayoutParams();
//设置左边距
marginLayoutParams.leftMargin = (int) animatorValue;
imgV_animator.setLayoutParams(marginLayoutParams);
}
});
//设置为无限
valueAnimator.setRepeatCount(INFINITE);
/**
* ValueAnimator.RESTART:重头开始执行动画
* ValueAnimator.REVERSE:执行到尽头之后,反过来执行动画
* 使用规则,只有当setRepeatCount()为INFINITE和整数值上面两个属性才能起作用
*/
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setTarget(imgV_animator); //设置需要动画的view
valueAnimator.start();
}
这里的效果图就不上了,暂时不会录GIF,见谅。只有一个静态效果图。
ObjectAnimator动画类
我们有了前面的ValueAnimator类,功能挺强大的了,为什么我们还需要ObjectAnimator类呢?
首先让我们去看看这个类是干嘛的。ObjectAnimator是ValueAnimator的一个子类。其实这个类说白了,就是在ValueAnimator的基础上,添加了set/get方法,这些方法是用来设置我们想要动画的函数的名字的,通过setPropertyName()和getPropertyName()两个对应的方法。
这又要怎么理解呢?我们知道在rotation旋转中,可以设置旋转的中心,例如代码就是下面就是根据自身中点为旋转中心,旋转360度。
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
那么我们在代码中就可以这样做了
void initView() {
//根据x轴选中360度
final ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imgV_animator2, "rotationX", 0, 360);
objectAnimator.setDuration(2000);
objectAnimator.setRepeatCount(INFINITE); //无限循环
objectAnimator.setInterpolator(new BounceInterpolator());
//添加动画更新时的监听,可以做一些操作
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
}
});
objectAnimator.start();
}
效果是imgV_animator2图片根据x轴,进行360的无限次数翻转。
上面的代码看不懂?没关系,待我慢慢道来。首先我们来看到构造函数
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {}
参数解析:
参数1:需要动画的view;
参数2:动作的名字;
参数3:float类型的集合;
关于参数2,我们可以这样理解:就是我需要进行那一个动作,比如rotationX,就是view根据x轴进行翻转多少度,翻转的度数由参数3决定。
下面我收集了一些动作的名字,因为比较多,难记,故要写下来,供自己查阅
rotationX:根据x轴翻转rotationY:根据y轴翻转
scaleX:根据x轴缩放
scaleY:根据y轴缩放
translationX:根据x轴平移
translationY:根据y轴平移
rotation:根据中心店翻转
to be continue
当然,这个类的构造函数比较多,以下的构造方法。
public static ObjectAnimator ofArgb(Object target, String propertyName, int... values) {}
public static <T> ObjectAnimator ofArgb(T target, Property<T, Integer> property, int... values) {}
public static <T> ObjectAnimator ofMultiInt(Object target, String propertyName,TypeConverter<T, int[]> converter, TypeEvaluator<T> evaluator, T... values) {}
public static ObjectAnimator ofMultiInt(Object target, String propertyName, Path path) {
public static ObjectAnimator ofMultiInt(Object target, String propertyName, int[][] values) {}
public static <T> ObjectAnimator ofInt(T target, Property<T, Integer> xProperty,
Property<T, Integer> yProperty, Path path) {
...
大家可以去阅读源码,看看都是干嘛用的。我这里就不做一一的解释了。我们还是看看怎么去使用。
关于ObjectAnimator类,上面说了,是可以利用set/get方法设置需要动作的名字的,如下就是将
final ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(imgV_animator2, "rotationX", 0, 10);
//设置动画的名称为rotationY
objectAnimator.setPropertyName("rotationY");
AnimatorSet类
AnimatorSet类继承Animator类,也是一个动画类。她的作用是:根据一定的顺序播放一个动画的集合。顺序分别有:一起播放,顺序播放和延时播放。
既然是一个集合,那么我就可以一次设置多几个需要动画的集合,然后按着我的顺序进行动画播放了。
下面是代码:
@TargetApi(Build.VERSION_CODES.KITKAT)
void animatorSet() {
AnimatorSet animatorSet = new AnimatorSet();
/*
ObjectAnimator obj1 = ObjectAnimator.ofFloat(imgV_animator, "scaleX", 1.0f,0.5f,1.0f);
ObjectAnimator obj2 = ObjectAnimator.ofFloat(imgV_animator, "scaleY", 1.0f,0.5f,1.0f);
ObjectAnimator obj3 = ObjectAnimator.ofFloat(imgV_animator, "rotationX", 0.0f,180.0f,0.0f);
//playobj1动画之后,跟着obj2动画
animatorSet.play(obj1).after(obj2);
animatorSet.play(obj2).after(obj3);
//设置共同播放
animatorSet.playTogether(obj1, obj2, obj3);
//设置播放的循序obj1-》ojb2-》ojb3
animatorSet.playSequentially(obj1, obj2, obj3);
animatorSet.start();
*/
//和上面的一毛一样,只是方法不同而已
animatorSet.playSequentially(
//重y轴-100(屏幕外)移动至0的位置
ObjectAnimator.ofFloat(imgV_animator, "translationY", -100, 0),
//在从0-1淡出来
ObjectAnimator.ofFloat(imgV_animator, "alpha", 0, 1));
animatorSet.setDuration(2000);
animatorSet.setStartDelay(2000);
//添加动画停止或者调用停止之后再重新播放动画
animatorSet.addPauseListener(new Animator.AnimatorPauseListener() {
@Override
public void onAnimationPause(Animator animation) {
//动画停止回调
}
@Override
public void onAnimationResume(Animator animation) {
//调用停止之后再重新播放动画的回调
}
});
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
//监听上一个动画结束之后,再进行缩放操作
AnimatorSet animatorSet2 = new AnimatorSet();
animatorSet2.playTogether(
//从1缩放到0.2在缩放到1的动画集合
ObjectAnimator.ofFloat(imgV_animator, "scaleX", 1f, 0.2f, 1f),
ObjectAnimator.ofFloat(imgV_animator, "scaleY", 1f, 0.2f, 1f)
);
animatorSet2.setInterpolator(new AccelerateInterpolator());
animatorSet2.setDuration(2000);
animatorSet2.start();
}
});
animatorSet.start();
}
*顺序的设定*:一起执行动画的方法playTogether(),有好几个重载方法;
设置顺序播放动画的方法:playSequentially(),也有好几个,基本上都是差不多的。大家可以都去试一试。**
具体的看代码就可以了。再说一句,imgV_animator/imgV_animator2都是imageview来的。
XML里面定义动画
当然,我们也是可以在XML文件里面设置上面几个动画的,在AnimatorSet类的开头就讲了。我们看看具体是怎么来写的。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<!--android:ordering="sequentially|together"
sequentially:按顺序
together:全部一起-->
<objectAnimator
android:duration="500"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="0.5"
android:valueType="floatType" />
<objectAnimator
android:duration="500"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="scaleY"
android:valueFrom="1.0"
android:valueTo="0.5"
android:valueType="floatType" />
<objectAnimator
android:duration="500"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="rotationX"
android:valueFrom="0.0"
android:valueTo="360.0"
android:valueType="floatType" />
<valueAnimator
android:duration="500"
android:interpolator="@android:anim/linear_interpolator"
android:propertyName="rotationX"
android:valueFrom="0.0"
android:valueTo="360.0"
android:valueType="floatType" />
</set>
这里我就不多讲了,你有看过四种动画 Android之动画(Java代码实现)1,那就可以理解XML中每个属性的意义了。
最后关于如何自定义速率
自定义速率,重写类,然后计算返回的因子。但是我还没有认真去研究,权当留白先了。等有时间在去看这里的内容。
public class CustomInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
// 编写相关的逻辑计算
//input *= 0.8f;
return input * input;
}
}
总结
上面的内容还是不少的,很多估计都没怎么接触过,但是只要多看几遍,你会发现,其实这个动画不难,并且用户巨大啊。想着明天我就可以在实战中使用了。共勉。
最后说一句,为毛在markdown编辑器上面会那么好看,但是来到CSDN上面就没那么好看了呢?!尤其是代码块的查看,颜色浅,很难看清的感觉。当然,好学的你是不会太在意这些问题的。
如有任何问题,请及时与我联系,谢谢!