内容简介:本篇文章已授权微信公众号 顾林海 独家发布Android中的动画分为三种:视图动画、帧动画以及属性动画,视图动画通过对View进行图像变换(平移、缩放、旋转、透明度)从而产生动画效果,帧动画可以通过顺序播放一系列图像从而产生动画,属性动画是API 11加入的,通过动态地改变对象的属性从而达到动画效果,接下来看看这三种动画的具体实现。帧动画比较简单,就是顺序播放一组预先定义好的图片,通过AnimationDrawable来使用,首先在xml文件中定义一个AnimationDrawable,frame_anim
本篇文章已授权微信公众号 顾林海 独家发布
Android中的动画分为三种:视图动画、帧动画以及属性动画,视图动画通过对View进行图像变换(平移、缩放、旋转、透明度)从而产生动画效果,帧动画可以通过顺序播放一系列图像从而产生动画,属性动画是API 11加入的,通过动态地改变对象的属性从而达到动画效果,接下来看看这三种动画的具体实现。
帧动画
帧动画比较简单,就是顺序播放一组预先定义好的图片,通过AnimationDrawable来使用,首先在xml文件中定义一个AnimationDrawable,frame_animation.xml文件如下:
<?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/p1" android:duration="500" /> <item android:drawable="@drawable/p2" android:duration="500" /> <item android:drawable="@drawable/p3" android:duration="500" /> </animation-list> 复制代码
以animation-list为标签,oneshot属性代表是否循环播放,false为循环播放,true代表只播放一次,内部通过一个个item标签设置每一帧播放的图片以及动画时长,将上面的drawable作为ImageView的背景:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/btn_frame" android:layout_width="match_parent" android:layout_height="40dp" android:text="帧动画"/> <ImageView android:id="@+id/iv_frame" android:layout_width="120dp" android:layout_height="120dp" android:layout_centerInParent="true" android:background="@drawable/frame_animation"/> </RelativeLayout> 复制代码
通过View的getBackground()方法获取AnimationDrawable对象,并通过AnimationDrawable的start()方法启动帧动画,代码如下:
public class MainActivity extends AppCompatActivity { private Button mFrameBtn; private ImageView mFrameIv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mFrameBtn=findViewById(R.id.btn_frame); mFrameIv=findViewById(R.id.iv_frame); mFrameBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AnimationDrawable animationDrawable= (AnimationDrawable) mFrameIv.getBackground(); animationDrawable.start(); } }); } } 复制代码
运行效果如下:
使用帧动画时需要注意每一帧图片的大小不要过大,否则会造成OOM。
视图动画
视图动画支持四种动画效果,分别是平移、缩放、旋转以及透明度。这四种动画既可以通过XML来定义,也可以通过代码来创建。
1、平移
XML定义:
在res/anim/下创建translate.xml:
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:fillAfter="true" android:duration="5000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="150" android:toYDelta="150" /> 复制代码
-
fillAfter表示动画结束后View是否停留在结束位置,true为停留在结束位置,false为不停留。
-
duration表示动画的持续时间。
-
fromXDelta表示x的起始值。
-
fromYDelta表示y的起始值。
-
toXDelta表示x的结束值。
-
toYDelta表示y的结束值。
-
interpolator表示插值器,插值器会影响动画的速度,常用的插值器如下:
android:interpolator="@android:anim/accelerate_interpolator" 设置动画为加速动画(动画播放中越来越快) android:interpolator="@android:anim/decelerate_interpolator" 设置动画为减速动画(动画播放中越来越慢) android:interpolator="@android:anim/accelerate_decelerate_interpolator" 设置动画为先加速在减速(开始速度最快 逐渐减慢) android:interpolator="@android:anim/anticipate_interpolator" 先反向执行一段,然后再加速反向回来(相当于我们弹簧,先反向压缩一小段,然后在加速弹出) android:interpolator="@android:anim/anticipate_overshoot_interpolator" 同上先反向一段,然后加速反向回来,执行完毕自带回弹效果(更形象的弹簧效果) android:interpolator="@android:anim/bounce_interpolator" 执行完毕之后会回弹跳跃几段(相当于我们高空掉下一颗皮球,到地面是会跳动几下) android:interpolator="@android:anim/cycle_interpolator" 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input) android:interpolator="@android:anim/linear_interpolator" 线性均匀改变 android:interpolator="@android:anim/overshoot_interpolator" 加速执行,结束之后回弹 复制代码
使用方式如下:
mTranslateBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animation animation=AnimationUtils.loadAnimation(MainActivity.this,R.anim.translate); mImageIv.startAnimation(animation); } }); 复制代码
通过AnimationUtils的静态方法loadAnimation加载translate文件,再通过View的startAnimation方法传入Animation对象并启动动画。
运行效果如下:
代码实现如下:
final TranslateAnimation translateAnimation=new TranslateAnimation(0,150,0,150); translateAnimation.setDuration(5000); translateAnimation.setFillAfter(true); translateAnimation.setInterpolator(new AccelerateInterpolator()); mTranslateBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImageIv.startAnimation(translateAnimation); } }); 复制代码
运行效果和上面的一样,其中interpolator、fillAfter以及duration也适用于其他三种动画效果,更多属性请查询官方文档。
2、缩放
XML定义:
在res/anim/下创建scale.xml
<?xml version="1.0" encoding="utf-8"?> <scale xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:interpolator="@android:anim/accelerate_interpolator" android:fromXScale="1" android:fromYScale="1" android:toXScale="0.5" android:toYScale="0.5" android:pivotX="50%" android:pivotY="50%"/> 复制代码
-
fromXScale表示水平方向缩放的起始值。
-
fromYScale表示竖直方向缩放的起始值。
-
toXScale表示水平方向的结束值。
-
toYScale表示竖直方向的结束值。
-
pivotX表示缩放的轴点的x坐标,缩放起点x轴坐标,取值可以是数值(50)、百分数(50%)、百分数p(50%p),当取值为数值时,缩放起点为View左上角坐标加具体数值像素,当取值为百分数时,表示在当前View左上角坐加上View宽度的具体百分比,当取值为百分数p时,表示在View左上角坐标加上父控件宽度的具体百分比。
-
pivotY表示缩放的轴点的y坐标,取值含义与pivotX相同。
使用方式如下:
mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animation animation=AnimationUtils.loadAnimation(MainActivity.this,R.anim.scale); mImageIv.startAnimation(animation); } }); 复制代码
运行效果:
代码实现如下:
final ScaleAnimation scaleAnimation = new ScaleAnimation(1, 0.5f, 1, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnimation.setDuration(5000); scaleAnimation.setFillAfter(true); scaleAnimation.setInterpolator(new AccelerateInterpolator()); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImageIv.startAnimation(scaleAnimation); } }); 复制代码
3、旋转
XML定义:
在res/anim/下创建rotate.xml:
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:interpolator="@android:anim/accelerate_interpolator" android:fromDegrees="0" android:toDegrees="360" android:repeatCount="-1" android:pivotX="50%" android:pivotY="50%"/> 复制代码
-
fromDegrees表示旋转的开始角度
-
toDegrees表示旋转的开始角度
-
repeatCount表示播放次数,-1表示循环播放
使用方式:
mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animation rotateAnimation=AnimationUtils.loadAnimation(MainActivity.this,R.anim.rotate); mImageIv.startAnimation(rotateAnimation); } }); 复制代码
运行效果:
代码实现如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = findViewById(R.id.btn_translate); mImageIv = findViewById(R.id.iv_image); final RotateAnimation rotateAnimation = new RotateAnimation(0,360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateAnimation.setDuration(2000); rotateAnimation.setFillAfter(true); rotateAnimation.setInterpolator(new AccelerateInterpolator()); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImageIv.startAnimation(rotateAnimation); } }); } 复制代码
4、透明度
XML定义:
在res/anim/下创建alpha.xml:
<?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:fillAfter="true" android:interpolator="@android:anim/accelerate_interpolator" android:fromAlpha="1" android:toAlpha="0" android:pivotX="50%" android:pivotY="50%"/> 复制代码
-
fromAlpha表示透明度的起始值
-
toAlpha表示透明度的结束值
使用方式:
mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animation animation=AnimationUtils.loadAnimation(MainActivity.this,R.anim.alpha); mImageIv.startAnimation(animation); } }); 复制代码
运行效果:
代码实现如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = findViewById(R.id.btn_translate); mImageIv = findViewById(R.id.iv_image); final AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f,0.0f); alphaAnimation.setDuration(2000); alphaAnimation.setFillAfter(true); alphaAnimation.setInterpolator(new AccelerateInterpolator()); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImageIv.startAnimation(alphaAnimation); } }); } 复制代码
除了上面单个执行动画外,我们可以同时执行多个,在xml中通过set标签,代码如下:
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_interpolator" android:fillAfter="false" android:shareInterpolator="true"> <alpha android:duration="2000" android:fromAlpha="1" android:toAlpha="0" android:pivotX="50%" android:pivotY="50%"/> <rotate android:duration="2000" android:fromDegrees="0" android:toDegrees="360" android:pivotX="50%" android:pivotY="50%"/> <scale android:duration="2000" android:fromXScale="1" android:fromYScale="1" android:toXScale="0.5" android:toYScale="0.5" android:pivotX="50%" android:pivotY="50%"/> <translate android:duration="2000" android:fromXDelta="0" android:fromYDelta="0" android:toXDelta="150" android:toYDelta="150" /> </set> 复制代码
使用方式:
mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animation animation=AnimationUtils.loadAnimation(MainActivity.this,R.anim.set); mImageIv.startAnimation(animation); } }); 复制代码
运行效果:
代码实现如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = findViewById(R.id.btn_translate); mImageIv = findViewById(R.id.iv_image); final AnimationSet animationSet=new AnimationSet(true); animationSet.setFillAfter(false); animationSet.setDuration(2000); AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f,0.0f); RotateAnimation rotateAnimation = new RotateAnimation(0,360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ScaleAnimation scaleAnimation = new ScaleAnimation(1, 0.5f, 1, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); TranslateAnimation translateAnimation=new TranslateAnimation(0,150,0,150); animationSet.addAnimation(alphaAnimation); animationSet.addAnimation(rotateAnimation); animationSet.addAnimation(scaleAnimation); animationSet.addAnimation(translateAnimation); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImageIv.startAnimation(animationSet); } }); } 复制代码
动画播放的相关操作可以通过AnimationListener接口来监听,实现方式如下:
final AnimationSet animationSet=new AnimationSet(true); animationSet.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { //动画开始 } @Override public void onAnimationEnd(Animation animation) { //动画结束 } @Override public void onAnimationRepeat(Animation animation) { //重复播放 } }); 复制代码
属性动画
属性动画是API 11新加入的,除了能实现上面视图动画的四种动画效果外,还可以持续更加绚丽的效果,同时修复了视图动画带来的不可点击的问题,当View通过视图动画进行一系列的操作后,比如向右偏移100,这时点击这个View时没有任何反应,点击一开始的位置,也就是空白的地方,会触发点击事件,事件不能随动画的变换而变化,新加入的属性动画修复了这些问题。下面主要介绍属性动画中的ValueAnimator、ObjectAnimator以及AnimatorSet等概念。
属性动画中使用ObjectAnimator进行更精细化的控制,控制一个对象和一个属性值,使用多个ObjectAnimator组合到AnimatorSet形成一个动画。属性动画可以通过属性get、set方法来真实地控制一个View的属性值。
ObjectAnimator
ObjectAnimator是属性动画中非常重要的类,创建一个ObjectAnimator只需要通过它的静态工厂类直接返回一个ObjectAnimator对象,参数包括一个对象和对象的属性名字,但这个属性必须有get和set方法,内部会通过反射机制来调用set方法修改对象的属性值。
private void animator(){ ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(mBtnNormal,"translationX",100); objectAnimator.setDuration(3000); objectAnimator.start(); } 复制代码
以上代码完成mBtnNormal按钮向右平移100。
可以给ObjectAnimator对象设置时长、插值器等属性。
View常用的属性动画的属性值有以下几种:
-
translationX和translationY:沿x轴或y轴进行平移。
-
rotation、rotationX、rotationY:按指定支点进行旋转。
-
PrivotX和PrivotY:设置支点位置。
-
alpha:透明度。
-
x和y:坐标位置。
使用ObjectAnimator时,被操作对象的属性值必须有set和get方法,如果没有,可以定义一个属性类或包装类来间接地给这个属性增加get和set方法。
ObjectAnimator提供了addListener方法:
private void animator(){ ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(mBtnNormal,"translationX",100); objectAnimator.setDuration(3000); //监听方式一 objectAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { super.onAnimationStart(animation); } @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); } }); //监听方式二 objectAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); objectAnimator.start(); } 复制代码
其中Animator.AnimatorListener必须实现它的4个方法,而AnimatorListenerAdapter可以按需实现相关方法。
ValueAnimator
ValueAnimator本身不会实现任何动画效果,可以通过它产生一定规律的数字,通过这些数字控制动画的实现过程,可以使用AnimatorUpdateListener来监听数值的变化。
private void valueAnimator(){ ValueAnimator animator=ValueAnimator.ofFloat(0,1000); animator.setDuration(3000); animator.setTarget(mBtnNormal); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value=animation.getAnimatedFraction(); } }); animator.start(); } 复制代码
AnimatorSet
AnimatorSet是组合动画,提供了一个play()方法,可以传入Animator对象(ObjectAnimator或ValueAnimator)。play()方法会返回一个AnimatorSet.Builder实例,内部提供了以下4个方法:
-
after(Animator anim):将现有动画插入到传入的动画之后执行。
-
after(long delay):将现有动画延迟指定毫秒后执行。
-
before(Animator anim):将现有动画插入到传入的动画之前执行。
-
with(Animator anim):将现有动画和传入的动画同时执行。
private void animatorSet(){ ObjectAnimator animator1=ObjectAnimator.ofFloat(mIvImage,"translationX",0,200,0); ObjectAnimator animator2=ObjectAnimator.ofFloat(mIvImage,"scaleX",1.0f,2.0f,1.0f); ObjectAnimator animator3=ObjectAnimator.ofFloat(mIvImage,"rotationX",0.0f,360.0f); AnimatorSet animationSet=new AnimatorSet(); animationSet.setDuration(3000); animationSet.play(animator1).with(animator2).after(animator3); animationSet.start(); } 复制代码
效果如下:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 动效无法落地? Lottie开源动画了解下。
- 面试官: css3动画了解吗? 我: .......
- 看你骨骼惊奇,这里有一套canvas粒子动画方案了解一下?
- 【Android 动画】动画详解之属性动画(三)
- 【Android 动画】动画详解之属性动画(五)
- Flutter 动画全解析(动画四要素、动画组件、隐式动画组件原理等)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。