在我们Android开发中,经常会使用到简单或者动画,这里就对Android开发中的动画做了一下简单的总结。
Android 动画分类
总的来说,Android动画可以分为两类,最初的传统动画和Android3.0 之后出现的属性动画;
传统动画又包括 帧动画(Frame Animation)和补间动画(Tweened Animation)。
一传统动画
1.帧动画
帧动画是最容易实现的一种动画,这种动画更多的依赖于完善的UI资源,他的原理就是将一张张单独的图片连贯的进行播放,
从而在视觉上产生一种动画的效果;而我们要做的就是:使用代码把一幅幅的图片按顺序显示。
我们来写上面逗比猫的动画:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/a_0"
android:duration="100" />
<item
android:drawable="@drawable/a_1"
android:duration="100" />
<item
android:drawable="@drawable/a_2"
android:duration="100" />
</animation-list>
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame_animation);
ImageView animationImg1 = (ImageView) findViewById(R.id.animation1);
animationImg1.setImageResource(R.drawable.frame_anim1);
AnimationDrawable animationDrawable1 = (AnimationDrawable) animationImg1.getDrawable();
animationDrawable1.start();
}
在有些代码中,我们还会看到android:oneshot="false" ,这个oneshot 的含义就是动画执行一次(true)还是循环执行多次。
上面其他几个动画实现方式都是一样,无非就是图片资源的差异。(其实我们小时看过的动画片大部分就是这样搞出来的)
2.补间动画
补间动画又可以分为四种形式,分别是** alpha(淡入淡出),translate(位移),scale(缩放大小),rotate(旋转)**。
补间动画的实现,一般会采用xml 文件的形式;代码会更容易书写和阅读,同时也更容易复用。
XML 实现
首先,在res/anim/
文件夹下定义如下的动画实现方式
alpha_anim.xml 动画实现
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="0.0" />
scale.xml 动画实现
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"/>
然后,在Activity中
Animation animation = AnimationUtils.loadAnimation(mContext, R.anim.alpha_anim);
img = (ImageView) findViewById(R.id.img);
img.startAnimation(animation);
这样就可以实现ImageView alpha
透明变化的动画效果。
也可以使用set 标签将多个动画组合(代码源自Android SDK API)
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@[package:]anim/interpolator_resource"
android:shareInterpolator=["true" | "false"] >
<alpha
android:fromAlpha="float"
android:toAlpha="float" />
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float" />
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float" />
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
<set>
...
</set>
</set>
可以看到组合动画是可以嵌套使用的。
各个动画属性的含义结合动画自身的特点应该很好理解,就不一一阐述了;这里主要说一下interpolator 和 pivot。
Interpolator 主要作用是可以控制动画的变化速率 ,就是动画进行的快慢节奏。
Android 系统已经为我们提供了一些Interpolator ,比如 accelerate_decelerate_interpolator,accelerate_interpolator等。更多的interpolator 及其含义可以在Android SDK 中查看。同时这个Interpolator也是可以自定义的,这个后面还会提到。
pivot 决定了当前动画执行的参考位置
pivot 这个属性主要是在translate 和 scale 动画中,这两种动画都牵扯到view 的“物理位置“发生变化,所以需要一个参考点。而pivotX和pivotY就共同决定了这个点;它的值可以是float或者是百分比数值。
我们以pivotX为例,
pivotX取值 | 含义 |
---|---|
10 | 距离动画所在view自身左边缘10像素 |
10% | 距离动画所在view自身左边缘 的距离是整个view宽度的10% |
10%p | 距离动画所在view父控件左边缘的距离是整个view宽度的10% |
pivotY 也是相同的原理,只不过变成的纵向的位置。如果还是不明白可以参考源码,在Tweened Animation中结合seekbar的滑动观察rotate的变化理解。
使用代码实现
有时候,动画的属性值可能需要动态的调整,这个时候使用xml 就不合适了,需要使用代码实现
private void RotateAnimation() {
animation = new RotateAnimation(-deValue, deValue, Animation.RELATIVE_TO_SELF,
pxValue, Animation.RELATIVE_TO_SELF, pyValue);
animation.setDuration(timeValue);
if (keep.isChecked()) {
animation.setFillAfter(true);
} else {
animation.setFillAfter(false);
}
if (loop.isChecked()) {
animation.setRepeatCount(-1);
} else {
animation.setRepeatCount(0);
}
if (reverse.isChecked()) {
animation.setRepeatMode(Animation.REVERSE);
} else {
animation.setRepeatMode(Animation.RESTART);
}
img.startAnimation(animation);
}
这里animation.setFillAfter决定了动画在播放结束时是否保持最终的状态;animation.setRepeatCount和animation.setRepeatMode 决定了动画的重复次数及重复方式,具体细节可查看源码理解。
好了,传统动画的内容就说到这里了,个人觉得传统动画真的是被时代的潮流推得很靠后了。
二.属性动画
属性动画是现在使用的最多的一种动画,顾名思义它是对于对象属性的动画。它比补间动画更加强大,所有补间动画的内容,都可以通过属性动画实现。
属性动画大致分为两种类型ViewPropertyAnimator和ObjectAnimator。
ViewPropertyAnimator:适合一些通用的动画,比如旋转、位移、缩放和透明,使用方式也很简单通过View.animate()即可得到ViewPropertyAnimator,之后进行相应的动画操作即可。
ObjectAnimator:适合用于为我们的自定义控件添加动画,当然首先我们应该在自定义View中添加相应的getXXX()和setXXX()相应属性的getter和setter方法,这里需要注意的是在setter方法内改变了自定义View中的属性后要调用invalidate()来刷新View的绘制。之后调用ObjectAnimator.of属性类型()返回一个ObjectAnimator,调用start()方法启动动画即可。
属性动画入门
首先我们来看看如何用属性动画实现上面补间动画的效果
private void RotateAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);
anim.setDuration(1000);
anim.start();
}
private void AlpahAnimation() {
ObjectAnimator anim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.8f, 0.6f, 0.4f, 0.2f, 0.0f);
anim.setRepeatCount(-1);
anim.setRepeatMode(ObjectAnimator.REVERSE);
anim.setDuration(2000);
anim.start();
}
这两个方法用属性动画的方式分别实现了旋转动画和淡入淡出动画,其中setDuration
、setRepeatMode
及setRepeatCount
和补间动画中的概念是一样的。
可以看到,属性动画貌似强大了许多,实现很方便,同时动画可变化的值也有了更多的选择,动画所能呈现的细节也更多。
当然一样牛逼的是属性动画也是可以组合实现
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(myView, "alpha", 1.0f, 0.5f, 0.8f, 1.0f);
ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(myView, "scaleX", 0.0f, 1.0f);
ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(myView, "scaleY", 0.0f, 2.0f);
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(myView, "rotation", 0, 360);
ObjectAnimator transXAnim = ObjectAnimator.ofFloat(myView, "translationX", 100, 400);
ObjectAnimator transYAnim = ObjectAnimator.ofFloat(myView, "tranlsationY", 100, 750);
AnimatorSet set = new AnimatorSet();
set.playTogether(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
// set.playSequentially(alphaAnim, scaleXAnim, scaleYAnim, rotateAnim, transXAnim, transYAnim);
set.setDuration(3000);
set.start();
可以看到这些动画可以同时播放,或者是按序播放。
动画监听器
您可以在动画持续时间期间使用下面描述的侦听器侦听重要事件。
-
Animator.AnimatorListener
-
onAnimationStart() - 动画启动时调用
。 -
onAnimationEnd() - 当动画结束时调用
。 -
onAnimationRepeat() - 当动画重演调用
。 -
onAnimationCancel()-当动画被取消调用。取消的动画还呼吁onAnimationEnd(),无论他们是如何结束
。 -
ValueAnimator.AnimatorUpdateListener
-
onAnimationUpdate()-称为动画的每一帧上。 听此事件使用所产生的计算值ValueAnimator动画中。 要使用该值,查询ValueAnimator传递到事件来获取与当前动画值对象getAnimatedValue()方法。 实现这个监听器
。
根据什么属性或对象的动画,你可能需要调用invalidate()上查看迫使屏幕的该区域的新的动画值重绘自身。 例如,对Drawable对象的颜色属性进行动画处理只会在该对象重绘本身时更新屏幕。 所有在查看属性制定者,如setAlpha()和setTranslationX()正确无效视图,所以你不需要调用这些方法与新的值时无效视图。
在XML声明动画
属性动画系统允许您使用XML声明属性动画,而不是以编程方式。 通过在XML中定义动画,您可以轻松地在多个活动中重复使用动画,并更轻松地编辑动画序列。
为了区分使用与那些使用旧的新的属性动画的API动画文件观看动画框架,开始与Android 3.1,你应该保存XML文件在属性动画res/animator/目录下。
以下属性动画类通过以下XML标记支持XML声明:
ValueAnimator - <animator>
ObjectAnimator - <objectAnimator>
AnimatorSet - <set>
下面的示例播放两套对象的动画顺序,第一组嵌套组一起编写两个对象的动画:
<set android:ordering="sequentially">
<set>
<objectAnimator
android:propertyName="x"
android:duration="500"
android:valueTo="400"
android:valueType="intType"/>
<objectAnimator
android:propertyName="y"
android:duration="500"
android:valueTo="300"
android:valueType="intType"/>
</set>
<objectAnimator
android:propertyName="alpha"
android:duration="500"
android:valueTo="1f"/>
</set>
为了运行这个动画,必须在代码中的充气XML资源AnimatorSet对象,然后开始动画集之前为所有动画的目标对象。呼叫setTarget()设置的所有儿童的单一目标对象AnimatorSet的方便。下面的代码演示如何做到这一点:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
R.anim.property_animator);
set.setTarget(myObject);
set.start();
当然了,关于动画已经有好多NB的开源动画库了例如Lottie动画库,Facebook-Rebound 弹性动画库
本文参考链接:http://www.jianshu.com/p/420629118c10
嗨~我是夏尼采,一个有梦想的IT
每周输出1篇有用的文章。
如果文章对您有帮助,希望能点个赞或者关注我。
您的关注和点赞是对我最大的鼓励,感谢您的阅读