Android中的动画和原理(帧动画和补间动画)
16lz
2021-01-26
1、Android中的动画分类
Android中的动画可以分为三类:帧动画,补间动画,和属性动画
动画分类 | 说明 |
---|---|
帧动画 | 通过不停的播放图片产生的动画效果 |
补间动画 | 对View的平移,旋转,缩放,透明产生效果 |
属性动画 | 动态的改变属性产生动画效果 |
2、帧动画及其原理
原理
帧动画是按照一定的顺序播放一系列图片,从而产生动画。和我们看的动漫原理是一样的,本质上是对图片快速的翻页产生动的效果。
帧动画依赖于图片。
示例代码:
<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/rocket_thrust1" android:duration="100" /> <item android:drawable="@drawable/rocket_thrust2" android:duration="100" /> <item android:drawable="@drawable/rocket_thrust3" android:duration="100" />animation-list>
调用
public class MainActivity extends AppCompatActivity { AnimationDrawable rocketAnimation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ImageView animationImg = (ImageView) findViewById(R.id.imageView); animationImg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { animationImg.setImageResource(R.drawable.play); AnimationDrawable animationDrawable1 = (AnimationDrawable) animationImg.getDrawable(); animationDrawable1.setOneShot(true); animationDrawable1.start(); } }); }}
3、补间动画及其原理
原理
补间动画的原理是对通过对View的平移,缩放,旋转和透明的操作,从而产生的动画。
注意:补间动画只调整View在Canvas上显示,并没有真实的改变View原来的位置,因此它的点击和触摸事件还保留在没有经过动画前的位置。
动画 | 说明 | 类 |
---|---|---|
平移 | 移动View的位置 | TranslateAnimation |
缩放 | 对View的缩放 | ScaleAnimation |
旋转 | 对View的旋转 | RotateAnimation |
透明 | 改变View的透明度 | AlphaAnimation |
<?xml version="1.0" encoding= "utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <alpha android:duration="3000" android:fromAlpha="0.0" android:toAlpha="1.0" /> <scale android:duration="3000" android:fromXScale="0.0" android:fromYScale="0.0" android:pivotX="50%" android:pivotY="50%" android:toXScale="1.0" android:toYScale="1.0" /> <rotate android:duration="3000" android:fromDegrees="0" android:pivotX="50%" android:pivotY="50%" android:toDegrees="720" /> <translate android:duration="1000" android:fromXDelta="0" android:fromYDelta="0" android:startOffset="3000" android:toXDelta="85" android:toYDelta="0" />set>
补间动画既可以在xml文件中配置,也可以用Java代码实现:
public class MainActivity extends AppCompatActivity { private ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = (ImageView) findViewById(R.id.imageView); TranslateAnimation translateAnim = new TranslateAnimation(0, 200, 0, 200); translateAnim.setDuration(3000); translateAnim.setFillAfter(true); imageView.startAnimation(translateAnim); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //经过平移后的View不相应点击事件,点击事件仍然在没有移动前。 Toast.makeText(MainActivity.this, "123", Toast.LENGTH_SHORT).show(); } }); }}
原理
1、调用View的startAnimation()方法出发动画事件。
public void startAnimation(Animation animation) { animation.setStartTime(Animation.START_ON_FIRST_FRAME); setAnimation(animation); invalidateParentCaches(); invalidate(true); }
在这个方法中,调用invalidate(true),触发调用draw()方法,对view进行重新绘制
2、draw()方法解析
把当前画布中View放置于矩阵中,然后通过矩阵变换对View在画布中影像进行改变。
Transformation 定义的矩阵对象
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) { ... if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) { parent.getChildTransformation().clear(); parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION; } ... //矩阵,把当前的View放置到矩阵中 Transformation transformToApply = null; //对View进行平移,旋转,缩放,透明等事件处理 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { if (transformToApply != null || !childHasIdentityMatrix) { int transX = 0; int transY = 0; if (offsetForScroll) { transX = -sx; transY = -sy; } 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); } parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } float transformAlpha = transformToApply.getAlpha(); if (transformAlpha < 1) { alpha *= transformAlpha; parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; } } if (!childHasIdentityMatrix && !drawingWithRenderNode) { canvas.translate(-transX, -transY); canvas.concat(getMatrix()); canvas.translate(transX, transY); } } // Deal with alpha if it is or used to be <1 if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) { if (alpha < 1) { mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA; } else { mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA; } parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION; if (!drawingWithDrawingCache) { final int multipliedAlpha = (int) (255 * alpha); if (!onSetAlpha(multipliedAlpha)) { if (drawingWithRenderNode) { renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha()); } else if (layerType == LAYER_TYPE_NONE) { canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(), multipliedAlpha); } } else { // Alpha is handled by the child directly, clobber the layer's alpha mPrivateFlags |= PFLAG_ALPHA_SET; } } } } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) { onSetAlpha(255); mPrivateFlags &= ~PFLAG_ALPHA_SET; } if (!drawingWithRenderNode) { // apply clips directly, since RenderNode won't do it for this draw if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) { if (offsetForScroll) { canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight()); } else { if (!scalingRequired || cache == null) { canvas.clipRect(0, 0, getWidth(), getHeight()); } else { canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight()); } } } if (mClipBounds != null) { // clip bounds ignore scroll canvas.clipRect(mClipBounds); } } ... return more; }
参考:
https://blog.csdn.net/mr_liabill/article/details/49510485
更多相关文章
- android 简单地设置Activity界面的跳转动画
- Android平台上大长图(图片很大的那种)的加载原理和方式
- Android补间动画详情
- 成佩涛编程之路——Android控件动画效果(二)
- 问题小结(14)-旋转动画Rotate
- Android分包原理
- Android(安卓)UI设计之自定义SwitchButton开关,实现类似IOS中UISw
- Android实现中轴旋转特效 Android制作别样的图片浏览器
- Android内存原理