南京哪个网站做物业贷,制作网页案例,wordpress外观,wordpress权限Android的三种动画详解#xff08;帧动画、View动画、属性动画#xff09;_android动画效果大全-CSDN博客
1、帧动画
缺点是#xff1a;占用内存较高#xff0c;播放的是一帧一帧的图片#xff0c;很少使用。
顺序播放预先定义的图片#xff0c;类似于播放视频。
步骤…Android的三种动画详解帧动画、View动画、属性动画_android动画效果大全-CSDN博客
1、帧动画
缺点是占用内存较高播放的是一帧一帧的图片很少使用。
顺序播放预先定义的图片类似于播放视频。
步骤
1).在drawable文件夹下创建一个animation_picture.xml文件,Root element选择为animation-list.
具体为右键点击drawable文件夹-New→Drawable Resource File 2配置自己需要播放的图片 ?xml version1.0 encodingutf-8? animation-list xmlns:androidhttp://schemas.android.com/apk/res/android android:oneshotfalse item android:drawabledrawable/food1 android:duration500/ item android:drawabledrawable/food2 android:duration500/ item android:drawabledrawable/food3 android:duration500/ item android:drawabledrawable/laojunshan1 android:duration500/ item android:drawabledrawable/laojunshan2 android:duration500/ /animation-list
上述xml中有些属性我们要了解到
1、android:oneshot“false” 表示是否重复播放动画还是只播放一次2、每个item都有Drawable和duration属性Drawable表示我们要播放的图片duration表示这张图播放的时间
3).将animation_picture.xml设置为imageview的播放资源 package com.example.animationtest; import androidx.appcompat.app.AppCompatActivity; import android.graphics.drawable.AnimationDrawable; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { private ImageView mImageView; private AnimationDrawable animationDrawable null; private boolean flag true; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button (Button) findViewById(R.id.animationButton); mImageView (ImageView)findViewById(R.id.image_view); mImageView.setBackgroundResource(R.drawable.animation_picture);//设置资源文件 animationDrawable (AnimationDrawable) mImageView.getBackground(); button.setOnClickListener(new View.OnClickListener() { Override public void onClick(View v) { if (flag) { animationDrawable.start();//开启动画 flag false; }else{ animationDrawable.stop(); flag true; } } }); } }
实际上从名字也可以看出AnimationDrawable是一个Drawable的子类所以我们定义的xml文件也是放在res/rawable目录下的.
2、View动画
View动画是补间动画设定起始和终止位置中间会自动补齐有平移、缩放、旋转、透明四种选择。对应的类为TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation。
view动画也称为补间动画因为我们只需要拿到一个view设定它开始和结束的位置中间的view会自动由系统补齐而不需要帧动画每一幅图都是提前准备好的。
View动画是Android一开始就提供的比较原始的动画主要支持四种效果平移、缩放、旋转、透明度变化渐变 四种基本效果我们可以再这四种基础效果的基础上选择其中的几种进行组合。 优点效率高使用方便。
缺点交互性差当动画结束后会回到初始位置对于交互性要求较高的使用属性动画。 (1) 作用对象局限于View (2) 动画效果单一仅能实现位移、旋转、缩放、透明度四种属性的改变 (3) 没有改变View真实属性
可以使用xml配置资源文件实现也可以用代码实现这里用代码实现。其中包含按钮控制动画和默认显示组合动画。
Bar.java package com.example.viewanimationtest; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import android.annotation.SuppressLint; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.AnimationSet; import android.view.animation.RotateAnimation; import android.view.animation.ScaleAnimation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.ImageView; import android.widget.Toast; /* *Since the child thread cannot directly modify the main UI, *it is implemented using the Handler mechanism. * */ public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private ImageView mImageView; public static final int TRANSLATE_ANI 1; public static final int ROTATE_ANI 2; public static final int SCALE_ANI 3; public static final int ALPHA_ANI 4; private Handler mHandler new Handler(Looper.getMainLooper()){ Override public void handleMessage(NonNull Message msg) { switch(msg.what) { case TRANSLATE_ANI: mImageView.clearAnimation();//When setting a new animation, first clear the previous animation. Animation translateAnimation new TranslateAnimation(0,500, 0,500);//The animation moves from0,0to (500,500). translateAnimation.setDuration(2000); mImageView.setAnimation(translateAnimation); break; case ROTATE_ANI: mImageView.clearAnimation(); Animation rotateAnimation new RotateAnimation(0,360, 0,0);//The animation rotates from 0° to 360° around00. rotateAnimation.setDuration(2000); mImageView.setAnimation(rotateAnimation); break; case SCALE_ANI: mImageView.clearAnimation(); Animation scaleAnimation new ScaleAnimation(0,1,0,1); scaleAnimation.setDuration(2000); mImageView.setAnimation(scaleAnimation); break; case ALPHA_ANI: mImageView.clearAnimation(); Animation alphaAnimation new AlphaAnimation(0,1); alphaAnimation.setDuration(2000); mImageView.setAnimation(alphaAnimation); break; default: Log.d(1111,default); break; } } }; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageView (ImageView)findViewById(R.id.image_view); Button translateButton (Button) findViewById(R.id.translate_button); Button scaleButton (Button) findViewById(R.id.scale_button); Button rotateButton (Button) findViewById(R.id.rotate_button); Button alphaButton (Button) findViewById(R.id.alpha_button); translateButton.setOnClickListener(this); scaleButton.setOnClickListener(this); rotateButton.setOnClickListener(this); alphaButton.setOnClickListener(this); mImageView.clearAnimation();//If some animations exist, clear them first. //set mix animation AnimationSet animationSet new AnimationSet(true); //set default alpha animation Animation alphaAnimation new AlphaAnimation(0,1);//The animation is from fully transparent to fully opaque. alphaAnimation.setDuration(2000);//The animation lasts 2 seconds. //set default scale animation Animation scaleAnimation new ScaleAnimation(0,1,0,1);//The animation is from 0% to 100%. scaleAnimation.setDuration(2000); //add sub-animations to combined animation animationSet.addAnimation(alphaAnimation); animationSet.addAnimation(scaleAnimation); //show the combined animation mImageView.setAnimation(animationSet); } SuppressLint(NonConstantResourceId) Override public void onClick(View v) { switch (v.getId()) { case R.id.translate_button: new Thread(new Runnable() { Override public void run() { Message msg new Message(); msg.what TRANSLATE_ANI; mHandler.sendMessage(msg); } }).start(); break; case R.id.rotate_button: new Thread(new Runnable() { Override public void run() { Message msg new Message(); msg.what ROTATE_ANI; mHandler.sendMessage(msg); } }).start(); break; case R.id.scale_button: new Thread(new Runnable() { Override public void run() { Message msg new Message(); msg.what SCALE_ANI; mHandler.sendMessage(msg); } }).start(); break; case R.id.alpha_button: new Thread(new Runnable() { Override public void run() { Message msg new Message(); msg.what ALPHA_ANI; mHandler.sendMessage(msg); } }).start(); break; default: break; } } }
具体效果
编辑view.mp4
3.属性动画
跟补间动画类似。具体内容可以参考文章
Android的三种动画详解帧动画、View动画、属性动画
在Android3.0以后引入了这种动画模式用来弥补传统的补间动画和帧动画的不足。属性动画的核心类如下图所示
其中Animator是属性动画的基类提供了一些通用的方法。AnimatorSet相当于一组属性动画的容器用来同时执行多个属性动画。app开发中常用的属性动画为ValueAnimator和ObjectAnimator本文将基于Android O的版本详细介绍ValueAnimator在系统中的实现方式。
优点交互性强动画结束时的位置就是最终位置。详细使用可参考Android进阶之光 书籍
代码实现
Bar.java package com.example.propertyanimation; import androidx.appcompat.app.AppCompatActivity; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.os.Bundle; import android.view.animation.AnimationSet; import android.widget.ImageView; import java.util.Set; public class MainActivity extends AppCompatActivity { private ImageView mImageview; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mImageview (ImageView) findViewById(R.id.image_view); //use AnimatorSet to show the combined animation AnimatorSet animatorSet new AnimatorSet(); //Use the ofFloat function to construct an ObjectAnimator object and set the alpha parameter. ObjectAnimator animator1 ObjectAnimator.ofFloat(mImageview, alpha,0f,1.0f); //Set the translationY parameter to move to a certain position along the Y axis ObjectAnimator animator2 ObjectAnimator.ofFloat(mImageview, translationY, 200); //Set the translationX parameter to move to a certain position along the X axis ObjectAnimator animator3 ObjectAnimator.ofFloat(mImageview, translationX, 200); //Set the rotation parameter to rotate a certain angle ObjectAnimator animator4 ObjectAnimator.ofFloat(mImageview, rotation, 180); //Magnify 0.5 times ObjectAnimator animator5 ObjectAnimator.ofFloat(mImageview, scaleX, 0.5f); //The animation lasts 2 seconds. animatorSet.setDuration(2000); //set the combined animation animatorSet.playTogether( animator1, animator2, animator3, animator4, animator5 ); //start the animation animatorSet.start(); } }
1.使用方法 private void testValueAnimator() { ValueAnimator valueAnimator ValueAnimator.ofInt(0, 100); valueAnimator.setDuration(300); valueAnimator.addListener(new Animator.AnimatorListener() { Override public void onAnimationStart(Animator animation) { Log.d(TAG, onAnimationStart); } Override public void onAnimationEnd(Animator animation) { Log.d(TAG, onAnimationEnd); } Override public void onAnimationCancel(Animator animation) { } Override public void onAnimationRepeat(Animator animation) { } }); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { Override public void onAnimationUpdate(ValueAnimator animation) { Log.d(TAG, fraction: animation.getAnimatedFraction() value: animation.getAnimatedValue()); } }); Log.d(TAG, testValueAnimator); valueAnimator.setStartDelay(100); valueAnimator.start(); } 其主要分为以下几个过程 (1) 创建ValueAnimator对象 通过ofXXX的静态方法获取 (2) 初始化参数 根据一系列setXXX/addXXX方法添加一些初始化参数和回调函数 (3) 开始动画 调用start方法 在使用属性动画时客户端通过ValueAnimator.AnimatorUpdateListener接口的回调函数onAnimationUpdate来监听每一帧的变化。属性动画顾名思义在动画过程中每一帧都会对预设的属性进行改变客户端通过每一帧该属性的变化自定义一些操作。其预设的属性就是在获取ValueAnimator对象时通过ofXXX方法设置的。上例中的ValueAnimator.ofInt(0, 100)则表示在该属性动画执行的过程中一个属性名为空字符串默认属性名后面会说到属性动画的属性名何时为默认何时为开发者自定义属性类型为整型的属性在0 ~ 100区间内递增的变化。在每一帧的回调中开发者可以通过ValueAnimator#getAnimatedValue方法获取默认属性值在该帧的值为多少。上例中的另一个方法ValueAnimator#getAnimatedFraction则表示该帧的动画进度0 ~ 1浮点数为多少。
2.动画初始化过程 (1) ofXXX方法设置动画属性类型及变化范围 初始化提供的方法有ofIntofFloatofArgb描述颜色的ARGB值的变化ofPropertyValuesHolder自定义的一系列PropertyValuesHolder使用该方法时会在动画每一帧分别处理添加进来的PropertyValuesHolder的变化ofObject使用该方法时需要自定义类型估值器。ofIntofFloatofObjectofArgb的实质都是先包装出一个对应的PropertyValuesHolder对象然后当动画驱动时根据这个对象计算数当前动画的进度fraction以及对应类型值在这一帧的取值animated value。ofPropertyValuesHolder方法相当于开发者自己创建若干PropertyValuesHolder对象在动画驱动时批处理这些对象。 如果使用ofPropertyValuesHolder需要开发者自己创建PropertyValuesHolder对象需要传入对应改变的属性的名字。如果使用其它初始化方法则属性名字默认为空字符串。客户端通过ValueAnimator#getAnimatedValue方法获取每一帧的属性值为多少如果调用无参的该方法则返回的是默认的属性值在当前帧的值因为默认的初始化方法确定了其属性类型并且只有一个。如果调用的是带String类型参数的该方法则返回的是对应名字的属性值在当前帧的值其名字是在创建PropertyValuesHolder对象时设置的。另外开发者也可以通过ValueAnimator#setValues方法主动添加PropertyValuesHolder对象进来。 综上无论通过哪种ofXXX方法进行初始化最终都会创建一个或多个PropertyValuesHolder对象这个类是用来管理属性动画中开发者定义的“属性”的变化每当动画进行时ValueAnimator对象会计算所有持有的PropertyValuesHolder对象在此帧的属性值为多少开发者可以通过getAnimatedValue获取。属性动画的核心也在于此——动画驱动过程中开发者可以自定义任意类型的对象的变化因此属性动画也打破了补间动画的局限性。 (2) addUpdateListener添加一个AnimatorUpdateListener的监听者 这个监听者的作用在于在动画驱动过程中每一帧都会通过该回调通知给客户端进程客户端可以在该回调中处理每一帧要做的事情。 (3) addListener添加一个AnimatorListener的监听者 这个监听者用来监听动画的开始/结束/取消/重复四个行为的发生。 (4) setDuration添加动画执行时长 (5) setCurrentFraction/setCurrentPlayTime 设置动画开始的动画进度/开始的时间点0 ~ Duration范围内
3.动画启动过程ValueAnimator#start() 动画启动过程的关键流程step表示上图中的步骤序号 step4向Choreographer中注册一个动画回调用来驱动整个动画流程。 step6 ~ step7初始化PropertyValuesHolder对象中的类型估值器默认只支持Int/Float两种类型的类型估值器其他类型需要自定义。 step8通知客户端注册的监听者动画开始AnimatorListener#onAnimationStart被回调。 step9 ~ step10设置动画开始时间以及开始时动画进度如果客户端没有主动通过setCurrentFraction/setCurrentPlayTime设置则默认会调用setCurrentPlayTime(0)表示动画从头开始。 step13 ~ step15入口为animateValue每一帧的动画都会调用到此方法该方法主要完成以下几件事 (1) 根据时间进度以及动画插值器计算出当前动画进度fraction (2) 根据当前动画进度以及类型估值器计算出当前PropertyValuesHolder在此帧中的取值是多少animated value (3) 回调AnimatorUpdateListener#onAnimationUpdate方法 启动时会调用该方法认为start方法触发的行为为第一帧Choreographer驱动的为第二帧 4.动画驱动过程Choreographer#doFrame