Android之动画
Android的动画可以分为三种,View动画、帧动画、属性动画。View动画通过对场景里的对象不断做图像变化(平移、缩放、旋转、透明度)从而产生动画效果,它是一种渐进式动画,而且View动画支持自定义。帧动画可以理解为图片切换动画(如果图片过多,会导致OOM)。属性动画为API11的新特性,属性动画通过通过动态地改变对象的属性从而达到动画效果。
- View动画
View动画的种类:View动画的四种变换效果对应着Animation的四个子类。TranslateAnimation,ScaleAnimation,RotateAnimation,AlphaAnimation。这四种动画可以通过XML来定义,也可以通过代码动态创建。对于View动画来说,建议XML来定义,这是因为XML格式的动画可读性好。
名称 | 标签 | 子类 | 效果 |
平移动画 | <translate> | TranslateAnimation | 移动View |
缩放动画 | <scale> | ScaleAnimation | 放大或缩小View |
旋转动画 | <rotate> | RotateAnimation | 旋转View |
透明度动画 | <alpha> | AlphaAnimation | 改变View的透明度 |
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:shareInterpolator="true"android:duration="1000"android:fillAfter="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>
View动画可以是单个动画,也可以是一系列动画组成。<set>表示动画集合,对应AnimationSet类。
android:interpolator:表示动画集合所使用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放速度。
android:shareInterpolator:表示集合中的动画是否共享同一个插值器。如果不指定插值器,那么子动画就需要单独指定所需要的插值器或者使用默认值。
AlphaAnimation anim = (AlphaAnimation) AnimationUtils.loadAnimation(this, R.anim.anim_test); TextView tv = findViewById(R.id.tv); tv.startAnimation(anim);
除了XML定义动画之外,还可以使用代码创建动画。
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1); alphaAnimation.setDuration(300); TextView tv = findViewById(R.id.tv); tv.startAnimation(alphaAnimation);
注意:通过Animation的setAnimationListener的方法可以给View动画添加过程监听。如适用于带动画的启动页,监听动画完成后进入MainActivity。
anim.setAnimationListener(new Animation.AnimationListener() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationEnd(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {} });
自定义View动画:
自定义View动画是一件简单而复杂的事情。说简单是:因为派生一种新动画只需要集成Animation这个抽象类,然后重写它的initialize和applyTransformation方法。在initialize中进行初始化工作,在applyTransformation中进行相应的矩阵变换即可。很多时候需要Camera来简化矩阵变换过程。说复杂,是因为需要运用到矩阵变换的过程,使用到数学上的概念。之后再做相关的分析讲解。
- 帧动画
帧动画顺序播放一组预先定义好的图片,类似电影播放。不同于View动画,系统提供另外一个类AnimationDrawable来使用帧动画。帧动画的使用比较简单,先使用XML来定义一个AnimationDrawable。在drawable目录下创建:
<?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/img1" android:duration="500"/><item android:drawable="@drawable/img2" android:duration="500"/><item android:drawable="@drawable/img3" android:duration="500"/> </animation-list>
将上述的Drawable作为View的背景并通过Drawable来播放动画。
TextView tv = findViewById(R.id.tv); tv.startAnimation(alphaAnimation); AnimationDrawable animationDrawable = (AnimationDrawable) tv.getBackground(); animationDrawable.start();
注意帧动画比较容易引起OOM,所以避免使用尺寸较大的图片。
- View动画的特殊场景使用
在一些特殊场景下,如ViewGroup中控制子元素的出场效果,在Activity中实现不同Activity之间的切换效果。
LayoutAnimation作用于ViewGroup,作为ViewGroup指定一个动画,这样当它的子元素出场时都具有这样的效果。常见的ListView的Item的出场以一定的动画效果出现。
定义LayoutAnimation如下:
//res/anim/anim_layout.xml<?xml version="1.0" encoding="utf-8"?> <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"android:delay="0.5"android:animationOrder="normal"android:animation="@anim/anim_item" />
delay表示子元素开始动画的时间延迟。比如说元素入场动画周期为300ms,那么0.5表示每个子元素都需要延迟150ms才能播放入场动画。第一个子元素延迟150ms开始播放入场动画,第二个子元素延迟300m开始播放入场,以此类推。
animationOrder:子元素动画顺序,normal, reverse和random。
android:animation: 为元素指定具体的入场动画。
为ViewGroup指定android:layoutAnimation属性,对于ListView而言,指定之后就是Item的出场动画了。除了XML中指定LayoutAnimation之外,还可以通过LayoutAnimationController来实现,具体如下:
ListView listView = findViewById(R.id.list_view); Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item); LayoutAnimationController controller = new LayoutAnimationController(animation); controller.setDelay(0.5f); controller.setOrder(LayoutAnimationController.ORDER_NORMAL); listView.setLayoutAnimation(controller);
Activity的切换效果:
Activity有默认的切换效果,但是这个效果是可以自定义的,主要用到overridePendingTransition(int enterAnim, int exitAnim)这个方法,这个必须在startActivity(intent)和finish()之后被调用才能生效,它的参数含义如下:
enterAnim - Activity被打开时,所需要的动画资源id
exitAnim - Activity被暂停时,所需要的动画资源id
当启动一个Activity时,可以按照如下方式为其添加自定义的切换效果:
Intent intent = new Intent(this, TestActivity.class); startActivity(intent); overridePendingTransition(R.anim.enter_anim, R.anim.exitAnim);
当Activityt退出时,也可以为其指定自定义的切换效果:
@Override public void finish() {super.finish();overridePendingTransition(R.anim.enter_anim, R.anim.exitAnim); }
Fragment也可以添加切换效果,可以通过FragmentTransaction中的setCustomAnimations()方法来添加切换动画,这个切换动画需要时View动画。还有其他的方法为Activity和Fragment添加切换动画,但是需要考略兼容为题。
- 属性动画
属性动画是API11新加入的特性,和View动画不同,它对作用的对象进行扩展,属性动画可以对任何对象做动画,甚至还可以没有对象。属性动画可以对任意对象的属性进行动画而不仅仅是View。属性动画中有ValueAnimator, ObjectAnimator和AnimatorSet等概念。为兼容之前的版本,采用nineoldandroids源动画库。
ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合。属性动画需要定义在res/animator/目录下。
- 改变一个对象myObject的translationY属性,让其沿着Y轴向上移动一段距离,在默认的时间完成。
ObjectAnimator.ofFloat(tv, "translationY", -myObject.getHeight()).start();
- 改变一个对象背景色属性,典型的改变View背景,下面的动画可以让背景色在3s内实现从0xFFFF8080到0xFF8080FF的渐变,动画会无限循环而且会有反转的效果。
ValueAnimator colorAnim = ObjectAnimator.ofInt(myObject, "backgroundColor", 0xFFFF8080, 0xFF8080FF);colorAnim.setDuration(3000);colorAnim.setEvaluator(new ArgbEvaluator());colorAnim.setRepeatCount(ValueAnimator.INFINITE);colorAnim.setRepeatMode(ValueAnimator.REVERSE);colorAnim.start();
- 动画集合,5秒内对View的旋转,平移,缩放和透明度都进行改变。
AnimatorSet set = new AnimatorSet(); set.playTogether(ObjectAnimator.ofFloat(view, "rotationX", 0, 360),ObjectAnimator.ofFloat(view, "rotationY", 0, 180),ObjectAnimator.ofFloat(view, "rotation", 0, -90),ObjectAnimator.ofFloat(view, "translationX", 0, 100),ObjectAnimator.ofFloat(view, "translationY", 0, 100),ObjectAnimator.ofFloat(view, "scaleX", 1, 1.5f),ObjectAnimator.ofFloat(view, "scaleY", 1, 0.5f),ObjectAnimator.ofFloat(view, "alpha", 1, 0.5f, 1) ); set.setDuration(5 * 1000).start();
属性动画除了代码实现之外,还可以通过XML来定义。
eg.
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"><objectAnimator android:propertyName="x"android:duration="300"android:valueTo="300"android:valueType="intType" /><objectAnimator android:propertyName="y"android:duration="300"android:valueTo="300"android:valueType="intType"/> </set>
加载上面的属性动画:
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.property_animator); set.setTarget(view); set.start();
建议:属性动画采用代码来实现,这是因为代码的方式会比较简单,更重要的是,在一个属性起始值无法确定的情况下,将无法将属性定义在xml文件中。
- 插值器和估值器
TimeInterpolater:时间插值器,它的作用是根据时间流逝的百分比来计算出当前属性改变的百分比,系统预置的有LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢,中间快),DeceleratrInterpolator(减速插值器:动画越来越慢)等。
TypeEvaluator:类型估值算法,也叫做估值器。它的作用是根据当前属性改变的百分比来计算改变后的属性值,系统预置的有IntEvaluator(针对整型属性),FloatEvaluator(针对浮点型属性),ArgbEvaluator(针对Color属性)。
线性差值器,属于匀速动画,其源码为:
/*** An interpolator where the rate of change is constant*/ @HasNativeInterpolator public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {public LinearInterpolator() {}public LinearInterpolator(Context context, AttributeSet attrs) {}public float getInterpolation(float input) {return input; /** 输入值和返回值一样 */}/** @hide */@Overridepublic long createNativeInterpolator() {return NativeInterpolatorFactoryHelper.createLinearInterpolator();} }
那到底输入数值是什么?这需要估值算法来确定,如整型估值器的源码为:
public class IntEvaluator implements TypeEvaluator<Integer> {/*** 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 * (v1 - v0)</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; should be of type <code>int</code> or* <code>Integer</code>* @param endValue The end value; should be of type <code>int</code> or <code>Integer</code>* @return A linear interpolation between the start and end values, given the* <code>fraction</code> parameter.*/public Integer evaluate(float fraction, Integer startValue, Integer endValue) {int startInt = startValue;return (int)(startInt + fraction * (endValue - startInt));} }
evaluate方法的三个参数分别是估值小数,起始值,结束值。例子:匀速动画,对象从0位置到100,当估值小数位0.5的时候,根据算法result = 0 + 0.5(100 - 0) = 50。
属性动画要求对象有该属性的set方法和get方法(可选)。除了系统预置的插值器和估值算法外,我们还可以自定义。自定义差值算法需要实现Interpolator或TimeInterpolator;自定义估值算法需要实现TypeEvaluator。
属性动画的监听:
有两个常用的属性动画监听:AnimatorListener, AnimatorUpdateListener
ObjectAnimator animator = new ObjectAnimator(); animator.addListener(new Animator.AnimatorListener() {@Overridepublic void onAnimationStart(Animator animation) {}@Overridepublic void onAnimationEnd(Animator animation) {}@Overridepublic void onAnimationCancel(Animator animation) {}@Overridepublic void onAnimationRepeat(Animator animation) {} });
从AnimatorListener的定义来看,它可以监听动画的开始,结束,取消和重复动画。
public static interface AnimatorUpdateListener {/*** <p>Notifies the occurrence of another frame of the animation.</p>** @param animation The animation which was repeated.*/void onAnimationUpdate(ValueAnimator animation);}
AnimatorUpdateListener比较特殊,它会监听整个动画过程,动画是由许多帧组成的,每播放一帧onAnimationUpdate()就会被调用一次,利用这个特征,我们可以做一些特殊事情。
- 对任意属性做动画
例如TextView的宽度动画变为800的动画,当layout_width的属性为wrap_content时,是有动画的,但是如果设置为固定值之后,下面的属性动画就没有效果了。
//高度从原来的默认值变为800 ObjectAnimator objectAnimator = ObjectAnimator.ofInt(textView, "width", 800); objectAnimator.setDuration(500); objectAnimator.start();
这是因为:
public void setWidth(int pixels) {mMaxWidth = mMinWidth = pixels;mMaxWidthMode = mMinWidthMode = PIXELS;requestLayout();invalidate(); }
public final int getWidth() {return mRight - mLeft;}
setWidth不是所谓意义上的宽度设置,所以就不会产生动画。对任意属性做动画,一般需要有set和get方法,设置流程如下:
如果没有属性设置获取权限,可以定义一个包裹类进行封装,实现set和get方法;如:
public static class ViewWrapper{private View mTarget;public ViewWrapper(View target){mTarget = target;}public void setWidth(int width){mTarget.getLayoutParams().width = width;mTarget.requestLayout();}public int getWidth(){return mTarget.getLayoutParams().width;} }
ViewWrapper viewWrapper = new ViewWrapper(view); ObjectAnimator widthAnimator = ObjectAnimator.ofInt(viewWrapper, "width", btn.getWidth(), 800).setDuration(500); widthAnimator.start();
这样,上面的TextView就可以实现宽度的动画效果了。
自定义View设置相关属性,进行动画案例:
/*** 自定义圆环* 对属性progress设置set和get方法* 就可以对CircleProgress的progress进行属性动画*/ public class CircleProgress extends View{private Paint mPaint;private RectF rectF;private int progress = 270;int width, height;public CircleProgress(Context context) {super(context);init();}public CircleProgress(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}public CircleProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init(){mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(20);mPaint.setColor(Color.RED);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);if (widthMode == MeasureSpec.EXACTLY){width = widthSize;}else{width = 100; //设置为默认值 }if (heightMode == MeasureSpec.EXACTLY){height = heightSize;}else{height = 100; //设置为默认值 }rectF = new RectF(20, 20, width-20, height-20);setMeasuredDimension(Math.min(width, height), Math.min(width, height)); //矩形 }@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawArc(rectF, -90, progress, false, mPaint);invalidate();}public void setProgress(int progress){this.progress = progress;}public int getProgress(){return progress;} }
转载于:https://www.cnblogs.com/denluoyia/p/8978045.html
Android之动画相关推荐
- android 自定义loading,Android自定义动画-StarLoadingView
今天来分享第二个自定义loading的动画,起了个名字叫 蹦跶的星星 ,还是老规矩先介绍,后上图. 实现效果在最后,GIF有点大,手机流量慎重. 介绍 首先声明做这个动画的初衷是为了学习和分享,所以从 ...
- android 三维动画效果,9款令人惊叹的HTML5 3D动画应用
原标题:9款令人惊叹的HTML5 3D动画应用 之前我们已经向大家分享了很多HTML5动画应用了,大部分都非常炫酷,也有一小部分是很实用的.今天我们要向各位HTML5动画爱好者介绍更多的HTML5 3 ...
- 【学习笔记】Android视图动画学习
2019独角兽企业重金招聘Python工程师标准>>> 1.Android View动画框架 Animation框架定义了透明度.旋转.缩放和位移几种常见的动画. 实现原理:每次绘制 ...
- android矢量动画 充电,android矢量动画
android矢量动画! 直接来个例子就明白了!(这里我把与动画无关的属性都用-表示) 首先你要有个矢量图 比如这个矢量图xml文件叫"vector1",文件在res\drawab ...
- Android视图动画集合AndoridViewAnimations
Android视图动画集合AndoridViewAnimations Android视图动画是针对视图对象的动画效果,包括对象平移.旋转.缩放和渐变四种类型.通过组合这四种类型,可以创建出无数种动画效 ...
- 使用android frame动画定义自己的ProgressBar
使用android frame动画定义自己的ProgressBar 在 res /layout/ainm 目录下面建一个frame_ainm.xml文件 <?xml version=&quo ...
- android动画封装,Android属性动画封装,快速构建动画
Android实现动画效果的方式主要有帧动画.补间动画.属性动画.关于安桌动画的基础知识可以查看这篇文章Android属性动画完全解析 这里我要讲的是如何快速构建出一个动画效果,如下图: 如果我们用属 ...
- Android m 自定义下拉菜单,Android实现动画效果的自定义下拉菜单功能
我们在购物APP里面设置收货地址时,都会有让我们选择省份及城市的下拉菜单项.今天我将使用Android原生的 Spinner 控件来实现一个自定义的下拉菜单功能,并配上一个透明渐变动画效果. 要实现的 ...
- Android Activity动画属性简介
Android Activity动画属性简介 在Android当中 设置activity的动画 需要复写 android:windowAnimationStyle这个属性 我们自定义一个动画样式来继承 ...
- Android 帧动画何时停止播放
为什么80%的码农都做不了架构师?>>> 关于android帧动画没有提供结束播放的接口回调表示不理解,也许是基于播放动画的时候,系统在干其他事情,无法确切地保证动画在tota ...
最新文章
- JS验证框架的使用方法
- python能写软件吗-python代码能做成软件吗
- Apache Kylin Cube 的构建过程
- c#启动单个程序(互斥机制)
- cocos2d-x android 入门
- windows 安装yaml支持和pytest支持等
- java线程池 core_Java 线程池 ThreadPoolExecutor 的使用
- 习题:编写一个程序,请输入两个数字,并判断两个数字的大小。
- 电脑安装系统安装不上的几个问题(解决)
- origin游戏下载一直显示准备中的解决方法
- 加壳及脱壳《逆向工程》
- Vue创建项目的详细步骤
- Oracle12C-针对log4j漏洞补丁修复
- JGIT使用的常见问题
- Ribbon原理及使用详解
- Microsoft Visual C++ 14.0 is required.
- ps去水印通用方法和教程案例
- WebBrowser抓图示例——截取网页上的验证码图片
- NPN、PNP型三极管的常见问题
- 哈工大计算机学院学号,【复试机试内容回忆汇总帖】2019年哈尔滨工业大学计算机考研...
热门文章
- Struts2笔记——struts常用标签
- Mathematics for Computer Graphics
- OCS Inventory NG使用之在windows 2008 R2平台下安装服务器端(二)
- 最新17个紫色风格网页设计作品欣赏
- 如何提高数据库访问效率
- 滴眼液的ph值与胶原纤维的粘结性(还没写完)
- flink的savepoints和checkpoints以及state Query(暂时无法全部完成)
- kill不掉 spark-submit
- sublime+virtualenv+pyspark执行的时候报Unable to load native-hadoop library for your platform
- 基于水色图像的水质评价