>类库下载 >java类库 >안드로이드의 애니메이션에 대한 첫 소개

안드로이드의 애니메이션에 대한 첫 소개

高洛峰
高洛峰원래의
2016-11-05 10:31:021648검색

애니메이션 효과는 인터페이스의 상호작용 효과를 크게 향상시킬 수 있습니다. 따라서 모바일 개발에서는 애니메이션 적용 시나리오가 더 일반적입니다. 기본적인 애니메이션 효과를 익히는 것은 성숙한 소프트웨어 개발에 필수적입니다. 또한 사용자는 텍스트나 그림보다 애니메이션에 대한 수용도가 훨씬 높습니다. 애니메이션 효과를 사용하면 제품에 대한 사용자의 인상이 깊어질 수 있습니다. 따라서 이 문서에서는 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 클래스를 사용하여 매트릭스의 일부 기본 사용법을 캡슐화하여 직접 사용할 수 있습니다. 코드로 이미지를 편집할 때는 원본 이미지를 처리하는 것보다 메모리에 있는 이미지의 복사본을 처리하는 것이 가장 좋습니다. 따라서 비트맵을 사용하여 원본 이미지와 동일한 크기와 형식의 빈 비트맵을 만들어야 합니다.

사진 작업 기본 단계:

1. 빈 비트맵을 만들고 원본 이미지와 일치하는 너비와 높이 정보를 저장합니다.

2. 작업판을 만듭니다. ;

3. 브러시를 만듭니다.

4. 행렬을 설정합니다.

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);
    }

다음으로 오늘의 주제로 넘어가겠습니다. Android의 애니메이션은 프레임 애니메이션, 보기 애니메이션(트윈 애니메이션), 속성 애니메이션의 세 가지 유형으로 구분됩니다. 이 세 가지 애니메이션을 아래에 소개합니다.

프레임 애니메이션:

프레임 애니메이션은 이 세 가지 애니메이션 중 가장 일반적인 것으로, 프레임 단위로 재생되는 애니메이션을 말합니다. 더 직설적으로 말하면 사진을 빠르게 전환하는 효과입니다. 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 이후 추가된 뷰 클래스 애니메이션 동작을 기록하는 데 사용되는 새로운 속성은 Android 3.0 이상을 실행하는 시스템에서만 실행할 수 있습니다. 즉, API-11 이상에서 실행되는 시스템을 의미합니다. 속성 애니메이션은 현재 보기의 위치를 ​​변경하고 컨트롤의 너비, 높이, 좌표 및 기타 속성을 동적으로 변경하여 애니메이션 효과를 생성합니다.

애니메이션 효과는 컨트롤의 속성을 제어하여 달성됩니다. 속성 애니메이션은 트위닝 애니메이션보다 훨씬 유연하고 강력합니다. 속성 애니메이션은 실제로 변위, 크기 조절, 투명도, 회전 및 기타 애니메이션을 구분하지 않는다는 점에 유의해야 합니다. 핵심 아이디어는 서로 다른 속성을 수정하여 트윈 애니메이션의 네 가지 효과를 얻을 수 있다는 것입니다.

     属性动画跟补间动画比,属性动画是真正改变了控件的属性,会改变当前的视图所在的位置,因此当控件的位置改变后只要点击到了控件“身上”就能触发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 文件中使用节点来定义。旋转动画在代码中使用的是RotateAnimation 类来定义,在XML 文件中使用节点来定义。伸缩动画在代码中使用的是ScaleAnimation 类来定义,在XML 文件中使用节点来定义。平移动画在代码中使用的是TranslateAnimation 类来定义,在XML 文件中使用节点来定义。Android 提供了AnimationSet 动画集合用于将多种补间动画联合起来一起使用,这样就能实现更多复杂的动画效果。动画集合既可以使用AnimationSet 类来定义也可以在XML 文件中使用节点来定义。任何复杂的动画均是通过简单的动画集合在一起的。

     使用编码方式同样可以实现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下的三种动画全部讲解完毕。

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.