android补间动画源码,腾讯Android社招面试源码相关11题+原理详解助你冲刺金九银十!...

Android源码相关面试专题

一、Android属性动画实现原理

工作原理:在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果。

5a7c0f68626d7d089d8c379c5e8e0dcf.png

1)ValueAnimator:通过不断控制值的变化(初始值->结束值),将值手动赋值给对象的属性,再不断调用View的invalidate()方法,去不断onDraw重绘view,达到动画的效果。

a3ac7113cd41977ef93907fdeb1e401d.png

1.1主要的三种方法:

a) ValueAnimator.ofInt(int values):估值器是整型估值器IntEaluator

b) ValueAnimator.ofFloat(float values):估值器是浮点型估值器FloatEaluator

c) ValueAnimator.ofObject(ObjectEvaluator, start, end):将初始值以对象的形式过渡到结束值,通过操作对象实现动画效果,需要实现Interpolator接口,自定义估值器

估值器TypeEvalutor,设置动画如何从初始值过渡到结束值的逻辑。插值器(Interpolator)决定值的变化模式(匀速、加速等);估值器(TypeEvalutor)决定值的具体变化数值。

// 自定义估值器,需要实现TypeEvaluator接口

public class ObjectEvaluator implements TypeEvaluator{

// 复写evaluate(),在evaluate()里写入对象动画过渡的逻辑*

@Override

public Object evaluate(float fraction, Object startValue, Object endValue) {

// 参数说明

// fraction:表示动画完成度(根据它来计算当前动画的值)

// startValue、endValue:动画的初始值和结束值

... // 写入对象动画过渡的逻辑

return value;

// 返回对象动画过渡的逻辑计算后的值

}

2)ObjectAnimator:直接对对象的属性值进行改变操作,从而实现动画效果

ObjectAnimator继承自ValueAnimator类,底层的动画实现机制还是基本值的改变。它是不断控制值的变化,再不断自动赋给对象的属性,从而实现动画效果。这里的自动赋值,是通过调用对象属性的set/get方法进行自动赋值,属性动画初始值如果有就直接取,没有则调用属性的get()方法获取,当值更新变化时,通过属性的set()方法进行赋值。每次赋值都是调用view的postInvalidate()/invalidate()方法不断刷新视图(实际调用了onDraw()方法进行了重绘视图)。

//Object 需要操作的对象; propertyName 需要操作的对象的属性; values动画初始值&结束值,

//如果是两个值,则从a->b值过渡,如果是三值,则从a->b->c

ObjectAnimator animator = ObjectAnimator.offloat(Object object, String propertyName, float ...values);

如果采用ObjectAnimator类实现动画,操作的对象的属性必须有get()和set()方法。

2.1 其他用法:

AnimatorSet组合动画

AnimatorSet.play(Animator anim) :播放当前动画

AnimatorSet.after(long delay) :将现有动画延迟x毫秒后执行

AnimatorSet.with(Animator anim) :将现有动画和传入的动画同时执行

AnimatorSet.after(Animator anim) :将现有动画插入到传入的动画之后执行

AnimatorSet.before(Animator anim) : 将现有动画插入到传入的动画之前执行

ViewPropertyAnimator直接对属性操作,View.animate()返回的是一个ViewPropertyAnimator对象,之后的调用方法都是基于该对象的操作,调用每个方法返回值都是它自身的实例

View.animate().alpha(0f).x(500).y(500).setDuration(500).setInterpolator()

设置动画监听

Animation.addListener(new AnimatorListener() {

@Override*

public void onAnimationStart(Animation animation) {

//动画开始时执行

}

@Override

public void onAnimationRepeat(Animation animation) {

//动画重复时执行

}

@Override

public void onAnimationCancel()(Animation animation) {

//动画取消时执行

}

@Override

public void onAnimationEnd(Animation animation) {

//动画结束时执行

}

}

);

2、补间动画实现原理

主要有四种AlpahAnimation\ ScaleAnimation\ RotateAnimation\ TranslateAnimation四种,对透明度、缩放、旋转、位移四种动画。在调用View.startAnimation时,先调用View.setAnimation(Animation)方法给自己设置一个Animation对象,再调用invalidate来重绘自己。在View.draw(Canvas, ViewGroup, long)方法中进行了getAnimation(), 并调用了drawAnimation(ViewGroup, long, Animation, boolean)方法,此方法调用Animation.getTranformation()方法,再调用applyTranformation()方法,该方法中主要是对Transformation.getMatrix().setTranslate/setRotate/setAlpha/setScale来设置相应的值,这个方法系统会以60FPS的频率进行调用。具体是在调Animation.start()方法中会调用animationHandler.start()方法,从而调用了scheduleAnimation()方法,这里会调用mChoreographer.postCallback(Choregrapher.CALLBACK_ANIMATION, this, null)放入事件队列中,等待doFrame()来消耗事件。

当一个 ChildView 要重画时,它会调用其成员函数 invalidate() 函数将通知其 ParentView 这个 ChildView 要重画,这个过程一直向上遍历到 ViewRoot,当 ViewRoot 收到这个通知后就会调用ViewRoot 中的 draw 函数从而完成绘制。View::onDraw() 有一个画布参数 Canvas, 画布顾名思义就是画东西的地方,Android 会为每一个 View 设置好画布,View 就可以调用 Canvas 的方法,比如:drawText, drawBitmap, drawPath 等等去画内容。每一个 ChildView 的画布是由其 ParentView 设置的,ParentView 根据 ChildView 在其内部的布局来调整 Canvas,其中画布的属性之一就是定义和 ChildView 相关的坐标系,默认是横轴为 X 轴,从左至右,值逐渐增大,竖轴为 Y 轴,从上至下,值逐渐增大。

30081c3779e87425db50b1b06eee3673.png

Android 补间动画就是通过 ParentView 来不断调整 ChildView 的画布坐标系来实现的,在ParentView的dispatchDraw方法会被调用。

dispatchDraw()

{

....

Animation a = ChildView.getAnimation()

Transformation tm = a.getTransformation();

Use tm to set ChildView's Canvas;

Invalidate();

....

}

这里有两个类:Animation 和 Transformation,这两个类是实现动画的主要的类,Animation 中主要定义了动画的一些属性比如开始时间、持续时间、是否重复播放等,这个类主要有两个重要的函数:getTransformation 和 applyTransformation,在 getTransformation 中 Animation 会根据动画的属性来产生一系列的差值点,然后将这些差值点传给 applyTransformation,这个函数将根据这些点来生成不同的 Transformation,Transformation 中包含一个矩阵和 alpha 值,矩阵是用来做平移、旋转和缩放动画的,而 alpha 值是用来做 alpha 动画的(简单理解的话,alpha 动画相当于不断变换透明度或颜色来实现动画),调用 dispatchDraw 时会调用 getTransformation 来得到当前的 Transformation。某一个 View 的动画的绘制并不是由他自己完成的而是由它的父 view 完成。

1)补间动画TranslateAnimation,View位置移动了,可是点击区域还在原来的位置,为什么?

View在做动画是,根据动画时间的插值,计算出一个Matrix,不停的invalidate,在onDraw中的Canvas上使用这个计算出来的Matrix去draw view的内容。某个view的动画绘制并不是由它自己完成,而是由它的父view完成,使它的父view画布进行了移动,而点击时还是点击原来的画布。使得它看起来变化了。

最后

漫漫开发之路,我们只是其中的一小部分……只有不断的学习、进阶,才是我们的出路!才跟得上时代的进步! 今年年初我花一个月的时间收录整理了一套知识体系,如果有想法深入的系统化的去学习的,可以点击传送门,我会把我收录整理的资料都送给大家,帮助大家更快的进阶。

789d16ecb93ff4aa13ed895a22c217c1.png

b2cd4ad2685af1f8f0e42eaa3285616e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值