android_动画框架
来源:互联网 发布:一起走数据怎么作弊 编辑:程序博客网 时间:2024/06/05 20:32
Android 动画框架
动画API介绍
View动画 (tween animation)
帧间动画(frmae animation)
属性动画 (Property Animation)
View 动画原理
以 AlphaAnimation 为例,AlphaAnimation new 以后,通常要调用View的startAnimation
startAnimation来执行动画:
alphaImageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Animation alphaAnimation = new AlphaAnimation(0, 1); alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); alphaAnimation.setDuration(5000); alphaImageView.startAnimation(alphaAnimation); } });
View#startAnimation 的具体方法:
/** * Start the specified animation now. * * @param animation the animation to start now */public void startAnimation(Animation animation) { animation.setStartTime(Animation.START_ON_FIRST_FRAME); setAnimation(animation); invalidateParentCaches(); invalidate(true);}
- 设置开始时间Animation.START_ON_FIRST_FRAME 其实是 -1;
- animation赋值 内部变量 mCurrentAnimation
- 调用 view 的invalidate(true),请求绘制重绘
回调postCallback
按照android 的View 绘制流程,invalideate 回调用到ViewRootImpl#invalidate -> ViewRootImpl#scheduleTraversals ->
Choreographer#postCallback
mChoreographer.postCallback( Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
当 SVNC 信号到来时,mTraversalRunnable 会被回调, 进入View 的重绘流程。
- ViewRootImpl#TraversalRunnable#run->
- ViewRootImpl->doTraversal->
- ViewRootImpl#performTraversals->
- ViewRootImpl#performDraw->
- ViewRootImpl#draw->
- ViewRootImpl#drawSoftware->
- View#draw(Canvas canvas)->
- ViewGroup#dispatchDraw->
- ViewGroup#drawChild->
- View#draw(Canvas canvas, ViewGroup parent, long drawingTime)
draw Animation
View 动画的出现在第10步中,可以看到这行函数:
final Animation a = getAnimation();
在一开始startAnimation的时候,setAnimation, 现在get了,然后调用applyLegacyAnimation。
/** * This method is called by ViewGroup.drawChild() to have each child view draw itself. * * This is where the View specializes rendering behavior based on layer type, * and hardware acceleration. */boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { ...... Transformation transformToApply = null; boolean concatMatrix = false; final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired; final Animation a = getAnimation(); if (a != null) { more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired); concatMatrix = a.willChangeTransformationMatrix(); if (concatMatrix) { mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM; } transformToApply = parent.getChildTransformation(); } else { ...... } ...... float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha()); if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { if (transformToApply != null || !childHasIdentityMatrix) { ...... if (transformToApply != null) { if (concatMatrix) { if (drawingWithRenderNode) { renderNode.setAnimationMatrix(transformToApply.getMatrix()); } else { // Undo the scroll translation, apply the transformation matrix, // then redo the scroll translate to get the correct result. canvas.translate(-transX, -transY); canvas.concat(transformToApply.getMatrix()); canvas.translate(transX, transY); } } float transformAlpha = transformToApply.getAlpha(); if (transformAlpha < 1) { alpha *= transformAlpha; parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } } ...... } } ....... if (a != null && !more) { if (!hardwareAcceleratedCanvas && !a.getFillAfter()) { onSetAlpha(255); } parent.finishAnimatingView(this, a); } if (more && hardwareAcceleratedCanvas) { if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { // alpha animations should cause the child to recreate its display list invalidate(true); } } return more;}
applyLegacyAnimation 函数
第一次进入 a.initialize 动画初始化。然后回调 onAnimationStart。
获取 parent 的ChildTransformation t, Transformation t = parent.getChildTransformation();然后对t 通过调用a.getTransformation 赋值。动画的API我们的主角终于出场了.applyLegacyAnimation 函数的结果是将计算后的Transformation 保存到parent.
/** * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common * case of an active Animation being run on the view. */private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime, Animation a, boolean scalingRequired) { Transformation invalidationTransform; final int flags = parent.mGroupFlags; final boolean initialized = a.isInitialized(); if (!initialized) { a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight()); a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop); if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler); onAnimationStart(); } final Transformation t = parent.getChildTransformation(); boolean more = a.getTransformation(drawingTime, t, 1f); if (scalingRequired && mAttachInfo.mApplicationScale != 1f) { if (parent.mInvalidationTransformation == null) { parent.mInvalidationTransformation = new Transformation(); } invalidationTransform = parent.mInvalidationTransformation; a.getTransformation(drawingTime, invalidationTransform, 1f); } else { invalidationTransform = t; } ...... draw(canvas); return more;}
继续回到draw 函数中:
transformToApply = parent.getChildTransformation();
获取 applyLegacyAnimation 计算后的Transformation,然后再
canvas.translate(-transX, -transY);canvas.concat(transformToApply.getMatrix());canvas.translate(transX, transY);
对canvas 做矩阵变换,动画效果已经出来。最后 draw(canvas);
对draw函数的总结就是:
- 获取Animation getAnimation()
- 调用 applyLegacyAnimation 根据根据动画运行时间调用Animation getTransformation 获取Transformation,然后将结果保存到parent.
- 调用 parent.getChildTransformation(); 获取保存的Transformation。
- 根据得到的Transformation 对canvas 的Matrix 做矩阵变换
- 调用draw(canvas) 绘制。
- 可以看出View动画没有改变View的坐标属性,只是在draw 的时候做了形变。
0 0
- android_动画框架
- Android_开源框架_NineOldAndroids动画库
- android_动画
- android_切换动画
- Android_属性动画
- android_属性动画
- android_动画总结
- Android_正弦波动画
- Android_基础动画
- Android_动画切换
- Android_动画:Interpolator
- Android_动画机制
- Android_属性动画
- Android_补间动画
- Android_补间动画
- android_属性动画
- Android_网络获取+动画
- Android_开发框架readme
- 利用socket上传图片
- A. Toda 2(优先队列)
- c语言学习笔记
- webview中Android和Js通讯互调并传参数
- 极客 - 博文29 - AVL树的平衡问题
- android_动画框架
- 《自己动手设计数据库》第10章 建立关系特性
- Java Swing 图形用户界面——菜单条、菜单与菜单项
- nginx-正则表达式
- C++中的头文件和源文件
- python 安装包
- Tensorflow设置显存自适应,显存比例
- ubuntu中安装lua5.3
- HDU 4857 逃生(拓扑排序+优先队列+反向建边)