Animation动画的解析
2015-12-07 18:30
483 查看
(转载)http://blog.csdn.net/jxxfzgy/article/details/45305629
Animation在View的包下,我们通过Animation的原理也可知道,Animation离开了View就没有效果,为什么这么说呢?
我们先看一个简单的Animation动画,AlphaAnimation:
public class AlphaAnimation extends Animation {
private float mFromAlpha;
private float mToAlpha;
/**
* Constructor used when an AlphaAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public AlphaAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation);
mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f);
mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f);
a.recycle();
}
/**
* Constructor to use when building an AlphaAnimation from code
*
* @param fromAlpha Starting alpha value for the animation, where 1.0 means
* fully opaque and 0.0 means fully transparent.
* @param toAlpha Ending alpha value for the animation.
*/
public AlphaAnimation(float fromAlpha, float toAlpha) {
mFromAlpha = fromAlpha;
mToAlpha = toAlpha;
}
/**
* Changes the alpha property of the supplied {@link Transformation}
*/
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
@Override
public boolean willChangeTransformationMatrix() {
return false;
}
@Override
public boolean willChangeBounds() {
return false;
}
/**
* @hide
*/
@Override
public boolean hasAlpha() {
return true;
}
}
代码非常简单,其核心代码就在
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
通过interpolatedTime来不断给变alpha的值,我们就可以看到一个View实现透明度变化的动画效果!那么问题来了,谁在调用applyTransformation方法呢?跟进代码看到
public boolean getTransformation(long currentTime, Transformation outTransformation){
}
中对applyTransformation做了调用,不用想了,getTransformation肯定是在View的startAnimation触发的!
是不是呢?
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
这里重新绘制了View,所以View的boolean draw(Canvas canvas, ViewGroup parent, long drawingTime)方法会被执行,为什么是draw而不是onDraw,我们看着么一句注解
/**
* This method is called by ViewGroup.drawChild() to have each child view draw itself.
* This draw() method is an implementation detail and is not intended to be overridden or
* to be called from anywhere else other than ViewGroup.drawChild().
*/
而在draw()方法中有
final Animation a = getAnimation();
if (a != null) {
more = drawAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
if (concatMatrix) {
mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
transformToApply = parent.getChildTransformation();
}
所以Animation得getTransformation的到执行,这就是Animation的实现原理。
但这好像对于我们来说意义不大,确实,因为我们不是Animation的缔造者,我们你只需要知道如何使用即可,就当前面热热身了!
Animation的使用非常简单,Android中已经为我们定义好了四种Animation动画效果AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation
以AlphaAnimation为例快速的说明一下其使用方法:
AlphaAnimation animation = new AlphaAnimation(1,0);
animation.setDuration(2000) ;
animation.setRepeat(2) ;
view.startAnimation(animation);
ok,一个View的动画就实现了,其他三个动画效果也是类似的,非常简单!这里不重复了,我们重点来看一下如何自己定义一个Animation效果,还是通过一个案例来说明。
实现一个按钮放大的动画效果,这里放大不能出现拉伸,如果可以拉伸那就没意义了,因为系统已经为我们定义好了一个,ScaleAnimation就可以实现;
第一步 、继承Animation,
第二步 、重写applyTransformation方法
第三步、没了!
所以代码如下:
/**
* Created by moon.zhong on 2015/4/23.
*/
public class ScaleAnimation extends Animation {
private View mTarget ;
private int mOriginWidth ;
private int mTargetWidth;
private ViewGroup.LayoutParams mParams ;
public ScaleAnimation(int mTargetWidth, View target) {
this.mTarget = target;
this.mOriginWidth = mTarget.getMeasuredWidth();
this.mTargetWidth = mTargetWidth;
if (mOriginWidth == 0 ){
mTarget.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mTarget.getViewTreeObserver().removeOnPreDrawListener(this);
mOriginWidth = mTarget.getMeasuredWidth() ;
return false;
}
});
}
mParams = target.getLayoutParams() ;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
/*interpolatedTime
* 变化范围
* 0~1
* */
mParams.width = (int) (mOriginWidth + (mTargetWidth - mOriginWidth)*interpolatedTime) ;
mTarget.setLayoutParams(mParams);
}
}
使用代码:
public void startAnimation(View view){
final float density = getResources().getDisplayMetrics().density;
int width = (int) (300 * density);
ScaleAnimation animation = new ScaleAnimation(width,mTargetView) ;
animation.setDuration(2000);
mTargetView.startAnimation(animation);
}
效果图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/09/fd80558f06b154860553f5a5eae0a94e)
再来一张拉伸的效果图对比:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/09/ae550cfef0a18b80b95fee552a9c9024)
总体来说还是非常简单的,这里我只是定义了一个简单的动画,同理定义一个复杂一点的动画也是同样的操作,只是applyTransformation里面的代码写的多一点而已。
本篇blog的知识点主要有:
1、Animation的运用场景,作用于View中;
2、系统Animation的使用
这种形式,当然还有读取xml的形式,这里没有提及到
3、自定义Animation
重写applyTransformation 方法
Demo源码
http://download.csdn.net/detail/jxxfzgy/8634819
//-------------------------------------------------------------------------------------------------------------
调用过程整理一下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202011/09/b067f021bcf7c5e7c033ddd143100e79)
这里使用了blumind软件来绘制思维导图,利于理清调用关系。
Animation在View的包下,我们通过Animation的原理也可知道,Animation离开了View就没有效果,为什么这么说呢?
Animation的动画原理
我们先看一个简单的Animation动画,AlphaAnimation:public class AlphaAnimation extends Animation {
private float mFromAlpha;
private float mToAlpha;
/**
* Constructor used when an AlphaAnimation is loaded from a resource.
*
* @param context Application context to use
* @param attrs Attribute set from which to read values
*/
public AlphaAnimation(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a =
context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.AlphaAnimation);
mFromAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_fromAlpha, 1.0f);
mToAlpha = a.getFloat(com.android.internal.R.styleable.AlphaAnimation_toAlpha, 1.0f);
a.recycle();
}
/**
* Constructor to use when building an AlphaAnimation from code
*
* @param fromAlpha Starting alpha value for the animation, where 1.0 means
* fully opaque and 0.0 means fully transparent.
* @param toAlpha Ending alpha value for the animation.
*/
public AlphaAnimation(float fromAlpha, float toAlpha) {
mFromAlpha = fromAlpha;
mToAlpha = toAlpha;
}
/**
* Changes the alpha property of the supplied {@link Transformation}
*/
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
@Override
public boolean willChangeTransformationMatrix() {
return false;
}
@Override
public boolean willChangeBounds() {
return false;
}
/**
* @hide
*/
@Override
public boolean hasAlpha() {
return true;
}
}
代码非常简单,其核心代码就在
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float alpha = mFromAlpha;
t.setAlpha(alpha + ((mToAlpha - alpha) * interpolatedTime));
}
通过interpolatedTime来不断给变alpha的值,我们就可以看到一个View实现透明度变化的动画效果!那么问题来了,谁在调用applyTransformation方法呢?跟进代码看到
public boolean getTransformation(long currentTime, Transformation outTransformation){
}
中对applyTransformation做了调用,不用想了,getTransformation肯定是在View的startAnimation触发的!
是不是呢?
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
这里重新绘制了View,所以View的boolean draw(Canvas canvas, ViewGroup parent, long drawingTime)方法会被执行,为什么是draw而不是onDraw,我们看着么一句注解
/**
* This method is called by ViewGroup.drawChild() to have each child view draw itself.
* This draw() method is an implementation detail and is not intended to be overridden or
* to be called from anywhere else other than ViewGroup.drawChild().
*/
而在draw()方法中有
final Animation a = getAnimation();
if (a != null) {
more = drawAnimation(parent, drawingTime, a, scalingRequired);
concatMatrix = a.willChangeTransformationMatrix();
if (concatMatrix) {
mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
}
transformToApply = parent.getChildTransformation();
}
所以Animation得getTransformation的到执行,这就是Animation的实现原理。
但这好像对于我们来说意义不大,确实,因为我们不是Animation的缔造者,我们你只需要知道如何使用即可,就当前面热热身了!
Animation的使用
Animation的使用非常简单,Android中已经为我们定义好了四种Animation动画效果AlphaAnimation、RotateAnimation、ScaleAnimation、TranslateAnimation 以AlphaAnimation为例快速的说明一下其使用方法:
AlphaAnimation animation = new AlphaAnimation(1,0);
animation.setDuration(2000) ;
animation.setRepeat(2) ;
view.startAnimation(animation);
ok,一个View的动画就实现了,其他三个动画效果也是类似的,非常简单!这里不重复了,我们重点来看一下如何自己定义一个Animation效果,还是通过一个案例来说明。
实现一个按钮放大的动画效果,这里放大不能出现拉伸,如果可以拉伸那就没意义了,因为系统已经为我们定义好了一个,ScaleAnimation就可以实现;
第一步 、继承Animation,
第二步 、重写applyTransformation方法
第三步、没了!
所以代码如下:
/**
* Created by moon.zhong on 2015/4/23.
*/
public class ScaleAnimation extends Animation {
private View mTarget ;
private int mOriginWidth ;
private int mTargetWidth;
private ViewGroup.LayoutParams mParams ;
public ScaleAnimation(int mTargetWidth, View target) {
this.mTarget = target;
this.mOriginWidth = mTarget.getMeasuredWidth();
this.mTargetWidth = mTargetWidth;
if (mOriginWidth == 0 ){
mTarget.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mTarget.getViewTreeObserver().removeOnPreDrawListener(this);
mOriginWidth = mTarget.getMeasuredWidth() ;
return false;
}
});
}
mParams = target.getLayoutParams() ;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
/*interpolatedTime
* 变化范围
* 0~1
* */
mParams.width = (int) (mOriginWidth + (mTargetWidth - mOriginWidth)*interpolatedTime) ;
mTarget.setLayoutParams(mParams);
}
}
使用代码:
public void startAnimation(View view){
final float density = getResources().getDisplayMetrics().density;
int width = (int) (300 * density);
ScaleAnimation animation = new ScaleAnimation(width,mTargetView) ;
animation.setDuration(2000);
mTargetView.startAnimation(animation);
}
效果图:
再来一张拉伸的效果图对比:
总结:
总体来说还是非常简单的,这里我只是定义了一个简单的动画,同理定义一个复杂一点的动画也是同样的操作,只是applyTransformation里面的代码写的多一点而已。 本篇blog的知识点主要有:
1、Animation的运用场景,作用于View中;
2、系统Animation的使用
<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">AlphaAnimation animation = new AlphaAnimation(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> animation<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setDuration</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2000</span>) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> animation<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.setRepeat</span>(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">2</span>) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span> View<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.startAnimation</span>(animation)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li></ul>
这种形式,当然还有读取xml的形式,这里没有提及到
3、自定义Animation
重写applyTransformation 方法
Demo源码
http://download.csdn.net/detail/jxxfzgy/8634819
//-------------------------------------------------------------------------------------------------------------
调用过程整理一下:
这里使用了blumind软件来绘制思维导图,利于理清调用关系。
相关文章推荐
- HTML 颜色名
- iOS耗电测试工具--batterydetective
- 使用git 新建分支以及管理分支
- activiti笔记三 Activiti问题重现
- PInvoke复习之深入理解char*与wchar_t*与string以及wstring之间的相互转换
- UITextField总结
- BZOJ2208 [JSOI2010] 连通数
- 关于项目的构建与打包
- IOS TableView的Cell高度自适应,UILabel自动换行适应
- javascript正则表达式
- HTML 颜色
- 第三个Sprint ------第一天
- 【第14周-查找项目1-4——验证平衡二叉树相关算法】
- shell之RDS备份+判断是否传输完成
- 第14周 项目1 - 验证算法 - 二叉排序树相关算法
- JSTL标签库核心标签C标签的使用
- javascript实现URL不缓存的方法
- 合成模式(Composite)-山下的养牛场
- 关闭Android/iPhone浏览器自动识别数字为电话号码
- 华为OJ中级题-字符串合并处理