内容简介:本篇文章已授权微信公众号 顾林海 独家发布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 动画全解析(动画四要素、动画组件、隐式动画组件原理等)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Don't Make Me Think
Steve Krug / New Riders Press / 18 August, 2005 / $35.00
Five years and more than 100,000 copies after it was first published, it's hard to imagine anyone working in Web design who hasn't read Steve Krug's "instant classic" on Web usability, but people are ......一起来看看 《Don't Make Me Think》 这本书的介绍吧!