补间动画使用说明

2019-08-23  本文已影响0人  取了个很好听的名字

1.背景

补间动画简介.png

2.使用场景

(1)View基础的动画效果(View的平移,缩放等)
(2)特殊的使用场景

2.1View基础的动画效果

平移效果


平移.gif

旋转效果


旋转.gif

缩放效果


缩放.gif

透明度效果


透明度.gif

2.2特殊场景的动画效果

Activity过场动画(淡入淡出,左右滑动等)
Fragment过场动画(淡入淡出,左右滑动等)


淡入淡出.gif 左右滑动.gif 出场动画.gif

3.使用方法

3.1核心类

动画名 动画说明 动画核心类
平移动画 移动View的位置 TranslateAnimation
旋转动画 旋转View的角度 RotationAnimation
缩放动画 缩放View的大小 ScaleAnimation
透明度动画 改变View的透明度 AlphaAnimation

3.2使用方式

补间动画的使用方式有两种方法:xml方式和代码方式

前者 可读性好
后者 能够动态设置

3.3.平移动画

XML方式
代码如下:

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="3000"//动画时长
    android:startOffset="1000"//动画开启时间时延
    android:fillBefore="false"//动画结束时是否会到最初的视图状态,默认为true
    android:fillEnabled="false"//是否允许动画结束时是否会到最初的视图状态 ,默认为true
    android:fillAfter="true"//动画结束时view是否停留在最后的视图状态,默认为false
    android:repeatMode="restart"//重复模式 restart为正序 reverse 逆序
    android:repeatCount="0"//动画重复次数
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"//设置动画插值器

    android:fromXDelta="0"  //动画开始时X方向的初始值
    android:toXDelta="200"  //动画结束时X方向的结束值
    android:fromYDelta="0" //动画开始时Y方向的初始值
    android:toYDelta="0"     //动画开始时Y方向的结束值
    >
</translate>

使用方法

  //平移
        Animation translationAnimation = AnimationUtils.loadAnimation(this, R.anim.animation_translate);
        tv.startAnimation(translationAnimation);

代码设置

  //平移
        //1. fromXDelta :视图在水平方向x 移动的起始值
        // 2. toXDelta :视图在水平方向x 移动的结束值
        // 3. fromYDelta :视图在竖直方向y 移动的起始值
        // 4. toYDelta:视图在竖直方向y 移动的结束值
        TranslateAnimation translateAnimation=new TranslateAnimation(0,0,0,200f);
        //动画时长
        translateAnimation.setDuration(3000);
        //动画开始时延
        translateAnimation.setStartOffset(1000);
        //是否应用fillBefore 默认为true
        translateAnimation.setFillEnabled(false);
        //是否允许动画结束后恢复到初始状态 默认为true
        translateAnimation.setFillBefore(false);
        //是否允许动画结束后恢复到最后的状态 默认为false
        translateAnimation.setFillAfter(true);
        //开启动画
        tv.startAnimation(translateAnimation);

3.4 旋转动画

XML方式

<?xml version="1.0" encoding="utf-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
   //动画开始时视图的旋转的角度
    android:fromDegrees="0"
   //动画结束时视图旋转的角度
    android:toDegrees="180"
    //是否允许fillBefore,默认为true
    android:fillEnabled="false"
    //动画结束时是否恢复初始的View视图状态 ,默认为true
    android:fillBefore="false"
   //动画结束时View视图状态是否停留在动画结束后的最后视图状态 ,默认为false
    android:fillAfter="true"
    //动画的插值器
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    //动画的重复模式 
    android:repeatMode="restart"
    //动画的重复次数
    android:repeatCount="0"
    //旋转轴的x坐标
    android:pivotX="50%"
    //旋转轴的y坐标
    android:pivotY="50%"
    android:duration="3000"
    android:startOffset="1000"
    ></rotate>
// pivotX pivotY,可取值为数字,百分比,或者百分比p
    // 设置为数字时(如50),轴点为View的左上角的原点在x方向和y方向加上50px的点。在Java代码里面设置这个参数的对应参数是Animation.ABSOLUTE。
    // 设置为百分比时(如50%),轴点为View的左上角的原点在x方向加上自身宽度50%和y方向自身高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_SELF。
    // 设置为百分比p时(如50%p),轴点为View的左上角的原点在x方向加上父控件宽度50%和y方向父控件高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_PARENT

使用方法

Animation rotationAnimation = AnimationUtils.loadAnimation(this, R.anim.animation_rotate);
tv.startAnimation(rotationAnimation);

代码设置

 RotateAnimation rotateAnimation=new RotateAnimation(0f,180f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
       //设置动画时长
       rotateAnimation.setDuration(3000);
       //设置动画开始时延
        rotateAnimation.setStartOffset(1000);
        //是否应用fillBefore
        rotateAnimation.setFillEnabled(true);
        //是否允许动画结束时恢复到初始状态
        rotateAnimation.setFillBefore(false);
        //动画结束时是否停留在动画结束的状态
        rotateAnimation.setFillAfter(true);
        //设置插值器
        rotateAnimation.setInterpolator(new AccelerateInterpolator());
        //开启动画
        tv.startAnimation(rotateAnimation);

3.5 缩放动画

XML设置

<?xml version="1.0" encoding="utf-8"?>
<scale
    xmlns:android="http://schemas.android.com/apk/res/android"
    //动画时长
    android:duration="3000"
    //动画开始时延
    android:startOffset="1000"
    //在动画开始时的x方向缩放倍数
    android:fromXScale="1.0"
    //在动画开始时的y方向缩放倍数
    android:fromYScale="1.0"
    //在动画结束时的x方向缩放倍数
    android:toXScale="0.5"
    //在动画结束时的y方向缩放倍数
    android:toYScale="0.5"
    //动画重复播放模式 restart 正序 reverse逆序 默认为restart
    android:repeatMode="restart"
    //动画重复播放次数
    android:repeatCount="0"
    //是否使fillBefore生效
    android:fillEnabled="false"
    //动画结束后是否恢复到动画开始时的视图
    android:fillBefore="false"
    //动画结束后是否停留在动画结束时的视图
    android:fillAfter="true"
    //设置插值器
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    //缩放时缩放轴的x坐标
    android:pivotX="50%"
    //缩放时缩放轴的y坐标
    android:pivotY="50%"
    ></scale>

使用方式

  //缩放
        Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.animation_scale);
        tv.startAnimation(scaleAnimation);

代码设置

  ScaleAnimation scaleAnimation=new ScaleAnimation(1f,0.5f,1f,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
        //设置动画时长
        scaleAnimation.setDuration(3000);
        //动画开始时的时延
        scaleAnimation.setStartOffset(1000);
        //是否允许fillBefore
        scaleAnimation.setFillEnabled(false);
        //动画结束时是否停留在view初始时的视图
        scaleAnimation.setFillBefore(false);
        //动画结束时是否停留在view结束时的视图
        scaleAnimation.setFillAfter(true);
        //设置插值器
        scaleAnimation.setInterpolator(new AccelerateInterpolator());
        //开启动画
        tv.startAnimation(scaleAnimation);

3.6 透明动画

XML设置

<?xml version="1.0" encoding="utf-8"?>
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    //初始时视图的透明度
    android:fromAlpha="1.0"
    //结束时视图的透明度
    android:toAlpha="0.5"
    //动画时长
    android:duration="3000"
    //动画开始时的时延
    android:startOffset="1000"
    //是否允许fillBefore,默认为true
    android:fillEnabled="false"
    //动画结束时是否恢复到初始时的view视图,默认为true
    android:fillBefore="false"
    //动画结束时是否停留在动画结束时的视图,默认为false
    android:fillAfter="true"
    //动画重复播放模式 restart正序 reverse 逆序 默认为restart
    android:repeatMode="restart"
    //动画重复播放次数
    android:repeatCount="0"
    //动画插值器
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    ></alpha>

使用方法

     //缩放动画
     Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.animation_alpha);
     tv.setAnimation(scaleAnimation);

代码设置

  AlphaAnimation alphaAnimation=new AlphaAnimation(1f,0.5f);
           //动画时长
           alphaAnimation.setDuration(3000);
           //动画开始时的时延
           alphaAnimation.setStartOffset(1000);
           //是否允许fillBefore
           alphaAnimation.setFillEnabled(false);
           //动画结束时是否恢复到初始的视图状态
           alphaAnimation.setFillBefore(false);
           //动画结束时停留在最后的视图状态
           alphaAnimation.setFillAfter(true);
           //设置插值器
           alphaAnimation.setInterpolator(new AccelerateInterpolator());
           //开启动画
           tv.startAnimation(alphaAnimation);

3.7 Activity的启动效果

Activity在进入/退出时的动画效果,主要包括淡入淡出,左右滑动等效果

系统定义

  //enterAnim  从MainActivity到SecondActivity时进入SecondActivity的动画效果
  //exitAnim   从MainActivity到SecondActivity时退出MainActivity时的动画效果
    overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);

方法实例:
activity_main:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhqy.viewanimationdemo.MainActivity">

    <Button
        android:id="@+id/btn_start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="开启"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        />

</android.support.constraint.ConstraintLayout>

MainActivity.java:

public class MainActivity extends AppCompatActivity {
    Button btn_start;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btn_start=findViewById(R.id.btn_start);
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //开启SecondActivity页面
                Intent intent=new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
                //启动动画
                //enterAnim  从MainActivity到SecondActivity时进入SecondActivity的动画效果
                //exitAnim   从MainActivity到SecondActivity时退出MainActivity时的动画效果
                overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);
            }
        });
    }
}

SecondActivity.java:

package com.zhqy.viewanimationdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }

    @Override
    public void finish() {
        super.finish();
        //关闭动画
        overridePendingTransition(android.R.anim.fade_in,android.R.anim.fade_out);
    }
}

测试效果:


进入退出动画.gif

自定义动画效果

自定义渐入渐出动画效果
anim_fadein.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0.0"
    android:toAlpha="1.0"
    android:duration="3000"
   ></alpha>

anim_fadeout.xml

<?xml version="1.0" encoding="utf-8"?>
<alpha
    android:fromAlpha="1.0"
    android:toAlpha="0.0"
    android:duration="3000"
    xmlns:android="http://schemas.android.com/apk/res/android"></alpha>

代码设置

  Intent intent=new Intent(MainActivity.this,SecondActivity.class);
  startActivity(intent);
   //启动动画
   //enterAnim  从MainActivity到SecondActivity时进入SecondActivity的动画效果
   //exitAnim   从MainActivity到SecondActivity时退出MainActivity时的动画效果
  overridePendingTransition(R.anim.anim_fadein,R.anim.anim_fadeout);

测试效果


自定义渐入渐出效果.gif

自定义左右滑动效果
anim_slideinright.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="100%p"
    android:toXDelta="0%p"
    android:duration="500"
    ></translate>

anim_slideinleft.xml

<?xml version="1.0" encoding="utf-8"?>
<translate
    android:fromXDelta="0%p"
    android:toXDelta="-100%p"
    android:duration="500"
    xmlns:android="http://schemas.android.com/apk/res/android"></translate>

代码使用

 //开启SecondActivity页面
                Intent intent=new Intent(MainActivity.this,SecondActivity.class);
                startActivity(intent);
                //启动动画
                //enterAnim  从MainActivity到SecondActivity时进入SecondActivity的动画效果
                //exitAnim   从MainActivity到SecondActivity时退出MainActivity时的动画效果
                overridePendingTransition(R.anim.anim_slideinright,R.anim.anim_slideinleft);

测试结果:


自定义左右滑动.gif

3.8 Fragment动画切换

类似于Activity,Fragment也带有类似的切换效果
MainActivity.class

public class MainActivity extends AppCompatActivity {
    Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn=findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                FragmentManager supportFragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = supportFragmentManager.beginTransaction();
                //自定义fragment动画
                fragmentTransaction.setCustomAnimations(R.anim.anim_slideinright,R.anim.anim_slideinleft);
                fragmentTransaction.replace(R.id.fl,new MyFragment());
                fragmentTransaction.commit();
            }
        });

    }
}

fragment_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:background="#0f0"
    >
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="MyFragment"
        android:textSize="30sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        />
</android.support.constraint.ConstraintLayout>

MyFragment.java

package com.zhqy.viewanimationdemo;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by jackal on 2019/8/23.
 */

public class MyFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View inflate = LayoutInflater.from(getContext()).inflate(R.layout.fragment_main, container, false);
        return inflate;
    }
}

测试效果


fragment进出场donghua.gif

3.9 ViewGroup中的进出场动画

视图组(ViewGroup)中子元素可以具备出场时的补间动画效果
常用需求场景:为RecyclerView的 item 设置出场动画
使用步骤如下:
1.ViewGroup子元素的出场动画 anim_view.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
   <translate
       android:fromXDelta="500"
       android:toXDelta="0"
       android:duration="500"
       ></translate>
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration="500"
        ></alpha>
</set>

2.设置 视图组(ViewGroup)的动画文件
anim_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation
    xmlns:android="http://schemas.android.com/apk/res/android"
    //子元素执行的时延
    //比如说动画时长为500ms,那么每个子元素执行动画的时延500*0.5=250ms
    //即第一个元素延时250ms,第二个元素延时500ms
    android:delay="0.5"
    //元素执行动画顺序
    //normal   子元素按顺序执行动画
    //reverse  子元素按逆序执行动画
    //random  子元素按随机顺序执行动画
    android:animationOrder="normal"
    //子元素执行的动画效果
    android:animation="@anim/anim_view"
    ></layoutAnimation>

3.设置layout动画
xml设置

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.zhqy.viewanimationdemo.MainActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rc"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layoutAnimation="@anim/anim_layout"
        ></android.support.v7.widget.RecyclerView>

</android.support.constraint.ConstraintLayout>

代码设置

 //加载子元素的动画
        rc=findViewById(R.id.rc);
        rc.setLayoutManager(new 
        LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
        rc.setAdapter(new MyAdapter(this));
        //加载子元素的动画
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_view);
        //设置LayoutAnimation属性
        LayoutAnimationController controller=new LayoutAnimationController(animation);
        controller.setDelay(0.5f);
        controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
        //添加LayoutAnimation
        rc.setLayoutAnimation(controller);

两者设置方式效果相同
测试结果


测试结果.gif

组合动画

即将单一的平移、缩放、透明度、旋转组合在一起就是组合动画
组合动画也有xml和代码设置两种方式
xml方式

<?xml version="1.0" encoding="utf-8"?>

<set
    xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="3000"
android:startOffset ="1000"
android:fillBefore = "true"
android:fillAfter = "false"
android:fillEnabled="true"
android:repeatMode="restart"
android:repeatCount = "0"
android:shareInterpolator = "true">
<rotate
    android:duration="1000"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatMode="restart"
    android:repeatCount="infinite"
    />


<translate
    android:duration="10000"
    android:startOffset = "1000"
android:fromXDelta="-50%p"
android:fromYDelta="0"
android:toXDelta="50%p"
android:toYDelta="0" />

<alpha
    android:startOffset="7000"
    android:duration="3000"
    android:fromAlpha="1.0"
    android:toAlpha="0.0" />



<scale
    android:startOffset="4000"
    android:duration="1000"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toXScale="0.5"
    android:toYScale="0.5" />


</set>

使用方法

  //动画集合
  Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_set);
  tv.startAnimation(animation);

代码方式

Button mButton = (Button) findViewById(R.id.Button);
// 创建 需要设置动画的 视图View

// 组合动画设置
AnimationSet setAnimation = new AnimationSet(true);
// 步骤1:创建组合动画对象(设置为true)

// 步骤2:设置组合动画的属性
// 特别说明以下情况
// 因为在下面的旋转动画设置了无限循环(RepeatCount = INFINITE)
// 所以动画不会结束,而是无限循环
// 所以组合动画的下面两行设置是无效的
setAnimation.setRepeatMode(Animation.RESTART);
setAnimation.setRepeatCount(1);// 设置了循环一次,但无效

// 步骤3:逐个创建子动画(方式同单个动画创建方式,此处不作过多描述)

// 子动画1:旋转动画
Animation rotate = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotate.setDuration(1000);
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatCount(Animation.INFINITE);

// 子动画2:平移动画
Animation translate = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT,-0.5f,
TranslateAnimation.RELATIVE_TO_PARENT,0.5f,
TranslateAnimation.RELATIVE_TO_SELF,0
,TranslateAnimation.RELATIVE_TO_SELF,0);
translate.setDuration(10000);

// 子动画3:透明度动画
Animation alpha = new AlphaAnimation(1,0);
alpha.setDuration(3000);
alpha.setStartOffset(7000);

// 子动画4:缩放动画
Animation scale1 = new ScaleAnimation(1,0.5f,1,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
scale1.setDuration(1000);
scale1.setStartOffset(4000);

// 步骤4:将创建的子动画添加到组合动画里
setAnimation.addAnimation(alpha);
setAnimation.addAnimation(rotate);
setAnimation.addAnimation(translate);
setAnimation.addAnimation(scale1);

mButton.startAnimation(setAnimation);
// 步骤5:播放动画

动画的监听

Animation类通过监听动画开始 / 结束 / 重复时刻来进行一系列操作,如跳转页面等等
通过在 Java 代码里setAnimationListener()方法设置

  animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                //动画执行时调用该方法
            }

            @Override
            public void onAnimationEnd(Animation animation) {
               //动画结束时执行此方法
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
               //动画重复播放时执行此方法
            }
        });

插值器

插值器的相关内容可以参考插值器(Interpolator)的使用说明

估值器

估值器的相关内容可以参考估值器(TypeEvaluator)的使用说明

以上就是补间动画的相关信息。

上一篇下一篇

猜你喜欢

热点阅读