补间动画使用说明
1.背景
补间动画简介.png2.使用场景
(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)的使用说明
以上就是补间动画的相关信息。