zoukankan      html  css  js  c++  java
  • 初识android中的动画

           动画效果可以大大提高界面的交互效果,因此,动画在移动开发中的应用场景较为普遍。掌握基本的动画效果在成熟的软件开发中不可或缺。除此之外,用户对于动画的接受程度远高于文字和图片,利用动画效果可以加深用户对于产品的印象。因此本文给出安卓设计中几种常见的动画效果。

           基础知识

           在介绍安卓中的动画效果之前,有必要介绍一下安卓中的图片处理机制。图片的特效包括图形的缩放、镜面、倒影、旋转、平移等。图片的特效处理方式是将原图的图形矩阵乘以一个特效矩阵,形成一个新的图形矩阵来实现的。矩阵Matrix 类,维护了一个3*3 的矩阵去更改像素点的坐标。Android 手机的屏幕坐标系以左上角为原点,从左向右为x轴正方向,从上到下为y轴正方向。第一行表示像素点的x 坐标:x = 1*x + 0*y + 0*z,第二行表示像素点的y 坐标:y = 0*x + 1*y + 0*z,第三行表示像素点的z 坐标:z = 0*x + 0*y + 1*z。图片的特效处理正是通过更改图形矩阵的值来实现的,在android下Matrix这个类帮我们封装了矩阵的一些基本用法,所以我们可以直接使用即可。用代码编辑图片,最好处理都是图片在内存中的拷贝,不去处理原图,因此需要用Bitmap创建一个与原图大小一致,格式相同的空白位图。

        对照片进行操作的基本步骤:

          1. 创建一个空白的bitmap,宽高信息和原图保存一致;

          2. 创建一个画板;

          3. 创建一个画笔;

          4. 设置matrix矩阵;

          5. 对照着原图在画纸上面画出一模一样的样子出来。

          下面分别给出对图片缩放、平移、旋转、镜面操作的代码。

    /**
         * 图片缩放
         * 
         */
        private void zoom() {
            Bitmap srcBitmap = BitmapFactory.decodeFile("mnt/sdcard/b.jpg");
            iv_src.setImageBitmap(srcBitmap);
            Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
            Canvas canvas = new Canvas(copyBitmap);
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            Matrix matrix = new Matrix();
            matrix.setScale(0.6f, 0.6f);
            canvas.drawBitmap(srcBitmap, matrix, paint);
            iv_dest.setImageBitmap(copyBitmap);
        }
        
        /**
         * 图片平移
         * 
         */
        public void translation(){
            Options ops = new Options();
            ops.inSampleSize = 4;   //等比放缩
            Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/b.jpg",ops);
            iv_src.setImageBitmap(srcBitmap);
            Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
            Canvas canvas = new Canvas(copyBitmap);
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            Matrix matrix = new Matrix();
            matrix.setTranslate(100, 100);
            canvas.drawBitmap(srcBitmap, matrix, paint);
            iv_dest.setImageBitmap(copyBitmap);
        }
        /**
         * 旋转
         * 
         */
        public void scole(){
            Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/b.jpg");
            iv_src.setImageBitmap(srcBitmap); 
            Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
            Canvas canvas = new Canvas(copyBitmap);
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            Matrix matrix = new Matrix();
            matrix.setRotate(180, srcBitmap.getWidth()/2, srcBitmap.getHeight()/2);//绕原点旋转
            canvas.drawBitmap(srcBitmap, matrix, paint);
            iv_dest.setImageBitmap(copyBitmap);
        }
        /**
         * 镜面特效/倒影特效
         * 原理一样,一个关于x轴旋转,一个关于y轴旋转
         */
        public void mirror(){
            Bitmap srcBitmap = BitmapFactory.decodeFile("/mnt/sdcard/b.jpg");
            iv_src.setImageBitmap(srcBitmap);
            Bitmap copyBitmap = Bitmap.createBitmap(srcBitmap.getWidth(), srcBitmap.getHeight(), srcBitmap.getConfig());
            Canvas canvas = new Canvas(copyBitmap);
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);
            Matrix matrix = new Matrix();
            matrix.setScale(-1, 1);
            matrix.postTranslate(srcBitmap.getWidth(), 0);
            canvas.drawBitmap(srcBitmap, matrix, paint);
            iv_dest.setImageBitmap(copyBitmap);
        }

            

           接下来进入进入今天的主题。安卓下的动画分为三种: 帧动画、View动画(补间动画)、属性动画。下面分别介绍这三种动画。 

           帧动画:

           帧动画是这三种动画中最为普遍的一种,指的是一帧一帧播放的动画。更直白的讲就是快速切换图片的效果。通过animation-list来实现,创建一个Drawable 序列,这些Drawable 可以按照指定的时间间隔一个一个的显示,也就是顺序播放事先做好的图像。

           帧动画使用的基本步骤:

             1 . 创建帧动画每帧需要的图片, 放到对应的 drawable-xxx 或drawable 目录中

             2 . 在drawable 目录下,创建帧动画 xml 文件,根节点选择 animation-list。oneshot属性表示帧动画的自动执行。 如果为true,表示动画只播放一次停止在最后一帧上,如果设置为false表示动画循环播放。

             3. 在JAVA代码中开启动画。设置为 View 的 Background 或者 ImageView 的 src,然后获取到控件的 AnimationDrawable 对象,通过 AnimationDrawable.start() 方法启动动画

             下面以火箭的发射为例演示帧动画。

              xml文件中的代码:

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android" >
       <item android:drawable="@drawable/desktop_rocket_launch_1" android:duration="200" />
       <item android:drawable="@drawable/desktop_rocket_launch_2" android:duration="200" />
    </animation-list>

             Java代码的实现:

            iv = new ImageView(this);
            //开启帧动画   rocket为上述xml文件
            iv.setBackgroundResource(R.drawable.rocket);
            AnimationDrawable ad = (AnimationDrawable) iv.getBackground();
            ad.start();

     

         属性动画:

         Android 3.0之后view类增加新的用来记录动画行为的属性,只能运行的Android3.0以上的系统也就是说 运行在 API-11 以上的系统。属性动画会改变当前的视图所在的位置,通过动态改变控件的宽、高、坐标等属性而产生的动画效果。

         通过控制控件的属性实现动画效果,属性动画比补间动画要更灵活、强大的多。需要注意的是属性动画内部其实并没有区分位移、缩放、透明、旋转等动画,其核心思想只是修改一个控件的属性,我们可以通过修改不同的属性来实现补间动画的4 种效果而已。

         属性动画跟补间动画比,属性动画是真正改变了控件的属性,会改变当前的视图所在的位置,因此当控件的位置改变后只要点击到了控件“身上”就能触发onClick 事件。而补间动画则并没用改变控件的真实属性,因此不管属性动画执行后将控件移动到了哪个位置,只能通过点击该控件的原始位置才能触发onClick 事件。

         通过xml 文件实现属性动画步骤:

         1. 在res 下创建属性动画文件。在res 目录下创建animator 文件夹,然后创建一个objectAnimator 资源文件。资源名称自定义即可。

         2. 编写属性动画文件。指定属性值。

         3. 编写代码使用属性动画文件。通过AnimatorInflater加载图片资源,指定要显示动画的控件,并开启动画。

         属性动画可以通过xml文件实现,但通常属性动画是通过JAVA代码实现。这里仅给出用xml文件实现淡化动画的案例,其他案例均以JAVA代码的方式实现。

         JAVA代码的方式实现属性动画。

    public class MainActivity extends Activity {
        private ImageView iv;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            iv = (ImageView) findViewById(R.id.iv);
        }
        /**
         * 淡化动画
         * @param view
         */
        public void alpha(View view) {
            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", new float[] {
                    0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f });
            oa.setDuration(3000);
            oa.setRepeatCount(ObjectAnimator.INFINITE);
            oa.setRepeatMode(ObjectAnimator.REVERSE);
            oa.start();
        }
        /**
         * 平移动画
         * @param view
         */
        public void trans(View view) {
            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX",
                    new float[] { 10f, 20f, 30f, 40f, 60f, 80f });
            oa.setDuration(3000);
            oa.setRepeatCount(ObjectAnimator.INFINITE);
            oa.setRepeatMode(ObjectAnimator.REVERSE);
            oa.start();
        }
        /**
         * 缩放动画
         */
        public void scale(View view) {
            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "scaleX", new float[] {
                    1f, 2f, 3f, 4f, 5f, 6f });
            oa.setDuration(3000);
            oa.setRepeatCount(ObjectAnimator.INFINITE);
            oa.setRepeatMode(ObjectAnimator.REVERSE);
            oa.start();
        }
    
        /**
         * 旋转动画
         */
        public void rotate(View view) {
            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "rotationY",
                    new float[] { 90f, 180f, 270f, 360f });
            oa.setDuration(3000);
            oa.setRepeatCount(ObjectAnimator.INFINITE);
            oa.setRepeatMode(ObjectAnimator.REVERSE);
            oa.start();
        }
    
        /**
         * 水平平移 + 竖直平移
         */
        public void set(View view) {
            AnimatorSet set = new AnimatorSet();
            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "translationX",
                    new float[] { 10f, 20f, 30f, 40f, 60f, 80f });
            oa.setDuration(3000);
            ObjectAnimator oa2 = ObjectAnimator.ofFloat(iv, "translationY",
                    new float[] { -10f, -20f, -30f, -40f, -60f, -80f });
            oa2.setDuration(3000);
            set.playTogether(oa, oa2);
            set.start();
        }
    
    }

           xml文件实现淡化效果:

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="3000"
        android:propertyName="alpha"
        android:repeatCount="3"
        android:repeatMode="reverse"
        android:valueFrom="0.0"
        android:valueTo="1.0" >
    
    </objectAnimator>

          

            然后在java代码中实现这样一段代码: 

          public void alpha(View view) {
              Animator animator = AnimatorInflater.loadAnimator(this,
                      R.animator.alpha);
              animator.setTarget(iv);
              animator.start();
          }

         

          View动画:

          渐变动画也叫补间动画。补间动画通过对View 的内容进行一系列的图形变换(包括平移、缩放、旋转、改变透明度)来实现动画效果。动画效果的定义可以采用XML 文件来做也可以采用java 代码来做。

          使用XML 文件实现View动画的步骤:

             1.  在res 目录下创建anim 文件夹。

             2.  在anim 文件夹中创建xml文件,文件名可以自定义。

             3.  编辑xml文件。定义不同的标签,表示不同的动画效果。alpha表示淡化,

             4.  添加Java 逻辑代码,使用AnimationUtils 工具类加载xml 文件,获取Animation 对象,调用startAnimation 让ImageView 执行此动画。

         View动画中常用属性的含义:

              duration 动画时长

              fromAlpha 起始透明度,1 为完全不透明,0 为完全透明

              repeatCount 重复次数,INFINITE表示无限重复

              toAlpha 目标透明度

              repeatMode 重复模式,restart 为重新开始,reverse表示来回播放

         渐变动画在代码中使用的是AlphaAnimation 类来定义,在XML 文件中使用<alpha>节点来定义。旋转动画在代码中使用的是RotateAnimation 类来定义,在XML 文件中使用<rotate>节点来定义。伸缩动画在代码中使用的是ScaleAnimation 类来定义,在XML 文件中使用<scale>节点来定义。平移动画在代码中使用的是TranslateAnimation 类来定义,在XML 文件中使用<scale>节点来定义。Android 提供了AnimationSet 动画集合用于将多种补间动画联合起来一起使用,这样就能实现更多复杂的动画效果。动画集合既可以使用AnimationSet 类来定义也可以在XML 文件中使用<set>节点来定义。任何复杂的动画均是通过简单的动画集合在一起的。

         使用编码方式同样可以实现view动画,直接创建相应的动画对象,然后添加相应的属。代使用编码方式实现view动画跟用XML 文件实现View动画其实是一模一样的,无非就是在JAVA代码中设定相关的属性罢了。

         使用XML 文件实现View动画的代码:  

         1 .   在anim文件夹下新建下列文件:

    <!-- alpha_demo.xml 文件夹下 -->
    <?xml version="1.0" encoding="utf-8"?>
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromAlpha="0.0"
        android:repeatCount="infinite"
        android:repeatMode="reverse"
        android:toAlpha="1.0" >
    </alpha>
    
    <!-- rotate_demo.xml 文件夹下 -->
    <?xml version="1.0" encoding="utf-8"?>
    <rotate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="2"
        android:repeatMode="reverse"
        android:toDegrees="360" >
    </rotate>
    
    <!-- scale_demo.xml 文件夹下 -->
    <?xml version="1.0" encoding="utf-8"?>
    <scale xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromXScale="20%"
        android:fromYScale="20%"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="2"
        android:repeatMode="reverse"
        android:toXScale="200%"
        android:toYScale="200%" >
    </scale>
    
    <!-- set_demo.xml 文件夹下   -->
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true" >
    
        <rotate
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:duration="2000"
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:repeatCount="2"
            android:repeatMode="reverse"
            android:toDegrees="360" >
        </rotate>
    
        <scale
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:duration="2000"
            android:fromXScale="20%"
            android:fromYScale="20%"
            android:pivotX="50%"
            android:pivotY="50%"
            android:repeatCount="2"
            android:repeatMode="reverse"
            android:toXScale="200%"
            android:toYScale="200%" >
        </scale>
    
    </set>
    
    <!-- trans_demo.xml 文件夹下 -->
    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="2000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:repeatCount="2"
        android:repeatMode="reverse"
        android:toXDelta="100%"
        android:toYDelta="100%" >
    </translate>

          2 .   在java代码中实现下列逻辑:

    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.view.View;
    import android.view.animation.Animation;
    import android.view.animation.AnimationUtils;
    import android.widget.ImageView;
    
    public class MainActivity extends Activity {
        private ImageView iv;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            iv = (ImageView) findViewById(R.id.iv);
        }
        /**
         * 淡化动画
         * @param view
         */
         public void alpha(View view){
             Animation aa = AnimationUtils.loadAnimation(this, R.anim.alpha_demo);
             iv.startAnimation(aa);
         }
    
         /**
          * 平移动画
          * @param view
          */
         public void trans(View view){
             Animation ta = AnimationUtils.loadAnimation(this, R.anim.trans_demo);
             iv.startAnimation(ta);
         }
         /**
          * 缩放动画
          */
         public void scale(View view){
             Animation sa = AnimationUtils.loadAnimation(this, R.anim.scale_demo);
             iv.startAnimation(sa);
         }
         /**
          * 旋转动画
          */
         public void rotate(View view){
             Animation ra = AnimationUtils.loadAnimation(this, R.anim.rotate_demo);
             iv.startAnimation(ra);
         }
         /**
          * 旋转 + 放缩
          */
         public void set(View view){
             Animation set = AnimationUtils.loadAnimation(this, R.anim.set_demo);
             iv.startAnimation(set);
         }
    }

           使用java代码实现View动画的代码

    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.view.View;
    import android.view.animation.AlphaAnimation;
    import android.view.animation.Animation;
    import android.view.animation.AnimationSet;
    import android.view.animation.AnimationUtils;
    import android.view.animation.RotateAnimation;
    import android.view.animation.ScaleAnimation;
    import android.view.animation.TranslateAnimation;
    import android.widget.ImageView;
    
    public class MainActivity extends Activity {
         private ImageView iv;
    
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
             iv = (ImageView) findViewById(R.id.iv);
         }
         /**
          * 渐变动画
          * @param view
          */
         public void alpha(View view) {
             AlphaAnimation aa = new AlphaAnimation(0.0f, 1.0f);
             aa.setDuration(2000);
             aa.setRepeatCount(Animation.INFINITE);
             aa.setRepeatMode(Animation.REVERSE);
             iv.startAnimation(aa);
         }
         /**
          * 平移动画
          * @param view
          */
         public void trans(View view) {
             TranslateAnimation ta = new TranslateAnimation(
                     Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1f,
                     Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1f);
             ta.setDuration(2000);
             ta.setRepeatCount(Animation.INFINITE);
             ta.setRepeatMode(Animation.REVERSE);
             iv.startAnimation(ta);
         }
         /**
          * 缩放动画
          */
         public void scale(View view) {
             ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f,
                     Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                     0.5f);
             sa.setDuration(2000);
             sa.setRepeatCount(Animation.INFINITE);
             sa.setRepeatMode(Animation.REVERSE);
             iv.startAnimation(sa);
         }
    
         /**
          * 旋转动画
          */
         public void rotate(View view) {
             RotateAnimation ra = new RotateAnimation(0, 360,
                     Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                     0.5f);
             ra.setDuration(2000);
             ra.setRepeatCount(Animation.INFINITE);
             ra.setRepeatMode(Animation.REVERSE);
             iv.startAnimation(ra);
         }
    
         /**
          *  旋转 + 平移 + 放缩
          *  AnimationSet添加各个动画
          */
         public void set(View view) {
             AnimationSet set = new AnimationSet(false);
             RotateAnimation ra = new RotateAnimation(0, 360,
                     Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                     0.5f);
             ra.setDuration(2000);
             ra.setRepeatCount(Animation.INFINITE);
             ra.setRepeatMode(Animation.REVERSE);
             ScaleAnimation sa = new ScaleAnimation(0.2f, 2.0f, 0.2f, 2.0f,
                     Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
                     0.5f);
             sa.setDuration(2000);
             sa.setRepeatCount(Animation.INFINITE);
             sa.setRepeatMode(Animation.REVERSE);
             TranslateAnimation ta = new TranslateAnimation(
                     Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1f,
                     Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1f);
             ta.setDuration(2000);
             ta.setRepeatCount(Animation.INFINITE);
             ta.setRepeatMode(Animation.REVERSE);
             set.addAnimation(ta);
             set.addAnimation(sa);
             set.addAnimation(ra);
             iv.startAnimation(set);
         }
    }

           

            自此Android下的三种动画全部讲解完毕。

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    年薪 80w 的程序员被鄙视了!工资再高,你也替代不了父母眼中的医师公!
    C语言中,能和指针并排核心知识的结构体,该如何掌握?
    编程的终点在何方?我似乎理解了编程的意义!为了在世上留下自己的痕迹!
    作为一个优秀的程序员,真的需要精通C语言吗?精通又需要多久的沉淀?
    用C语言验证 “6174黑洞之谜”!万物始于C,编程世界的黑洞!
    打印未决信号集
    信号捕捉
    alarm函数
    输入输出运算符重载
    自增自减运算符重载
  • 原文地址:https://www.cnblogs.com/huangjie123/p/6031605.html
Copyright © 2011-2022 走看看