Android中动画分类如下:
一、帧动画
帧动画的原理就是让一系列的静态图片依次播放,利用人眼“视觉暂留”的原理,实现动画。也就是说,看到的动画其实只是一张张的图片短暂的呈现。
1.用xml实现帧动画
在res/drawable中创建xml文件,一般格式如下
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true|false">
<item android:drawable="" android:duration=""/>
</animation-list>
接下来创建一组动画的图片:
fire_animate.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<!--
一个item对应一帧:一张图片
drawable:配置动画的图片
duration:配置这个图片在动画中中出现的时间 单位:毫秒
-->
<item android:drawable="@drawable/campfire01" android:duration="80"></item>
<item android:drawable="@drawable/campfire02" android:duration="80"></item>
<item android:drawable="@drawable/campfire03" android:duration="80"></item>
<item android:drawable="@drawable/campfire04" android:duration="80"></item>
<item android:drawable="@drawable/campfire05" android:duration="80"></item>
<item android:drawable="@drawable/campfire06" android:duration="80"></item>
<item android:drawable="@drawable/campfire07" android:duration="80"></item>
<item android:drawable="@drawable/campfire08" android:duration="80"></item>
<item android:drawable="@drawable/campfire09" android:duration="80"></item>
<item android:drawable="@drawable/campfire10" android:duration="80"></item>
<item android:drawable="@drawable/campfire11" android:duration="80"></item>
<item android:drawable="@drawable/campfire12" android:duration="80"></item>
<item android:drawable="@drawable/campfire13" android:duration="80"></item>
<item android:drawable="@drawable/campfire14" android:duration="80"></item>
<item android:drawable="@drawable/campfire15" android:duration="80"></item>
<item android:drawable="@drawable/campfire16" android:duration="80"></item>
<item android:drawable="@drawable/campfire17" android:duration="80"></item>
</animation-list>
在activity_main中创建一个ImageView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<ImageView
android:id="@+id/anim"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/campfire01"
android:scaleType="fitXY"
/>
</RelativeLayout>
最后,在MainActivity里面调用
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.获取动画的控件
ImageView fires = findViewById(R.id.anim);
//2.通过控件获取动画
AnimationDrawable animationDrawable = (AnimationDrawable) fires.getDrawable();
//3.启动动画
animationDrawable.start();
}
2. 使用java代码创建
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//1.创建一个动画资源
AnimationDrawable anim = new AnimationDrawable();
//2.添加每一帧的动画
int []ids = {R.drawable.campfire02,R.drawable.campfire03,R.drawable.campfire04,
R.drawable.campfire05,R.drawable.campfire06,R.drawable.campfire07,R.drawable.campfire08,
R.drawable.campfire09,R.drawable.campfire10,R.drawable.campfire11,R.drawable.campfire12,
R.drawable.campfire13,R.drawable.campfire14,R.drawable.campfire15,R.drawable.campfire16,R.drawable.campfire17};
for(int id : ids){
anim.addFrame(getResources().getDrawable(id),100);
}
//3.使用这个动画资源
ImageView iv = findViewById(R.id.anim);
iv.setImageDrawable(anim);
//4.启动动画
((AnimationDrawable)iv.getDrawable()).start();
}
}
效果图展示:
二、补间动画
Tween Animation叫补间动画,因为只需要给出动画的开始和结尾的‘ 关键帧 ’,而中间的部分由系统补足,但其视图本身属性等不随动画而改变。
比如,定义一个translate动画,向右移动了200dp,但它的原图没有移动,还是在原来的位置,只是呈现的这个视觉效果。
补间动画包括以下四种:
-
平移动画(TranslateAnimation)
-
缩放动画(ScaleAnimation)
-
旋转动画(RotateAnimation)
-
透明度动画(AlphaAnimation)
以上四种动画,皆继承于Animation,继承了以下Animation的通用属性和方法:
xml属性 | java方法 | 解释 |
---|---|---|
android:duration | setDuration(long) | 动画持续时间,毫秒为单位 |
android:ShareInterpolator | setInterpolator(Interpolator) | 设定插值器(指定的动画效果,譬如回弹等) |
android:fillAfter | setFillAfter(boolean) | 控件动画结束时是否保持动画最后的状态 |
android:fillBefore | setFillBefore(boolean) | 控件动画结束时是否还原到开始动画前的状态 |
android:repeatMode | setRepeatMode(int) | 重复类型有两个值,reverse表示倒序回放,restart表示从头播放 |
android:startOffset | setStartOffset(long)<span class="Apple-tab-span" | style="white-space:pre"></span> 调用start函数之后等待开始运行的时间,单位为毫秒 |
接下来使用AnimationSet的方式调用各个动画:
1.xml方式使用
1.在res目录下创建一个目录取名anim,若不行:切换为Project在下图路径下创建后,再切换回Android
2.在anim路径下创建一个xml,我取名为translate.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true"
android:repeatMode="reverse"/>
<translate
android:fromXDelta="0"
android:toXDelta="500"
android:fromYDelta="0"
android:toYDelta="500"
android:duration= "1000"
android:fillAfter="true"
android:repeatMode="reverse"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
/>
<!-- 缩放,宽高都是从 1 到 0
pivotX、pivotY 代表缩放中心点的横竖坐标
interpolator 代表动画模式,我设置为先加速、后减速-->
<scale
android:fromXScale="1"
android:toXScale="0"
android:fromYScale="1"
android:toYScale="0"
android:pivotY="50%"
android:pivotX="50%"
android:duration="1000"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fillAfter="true"
android:repeatMode="reverse"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0"
android:duration="1000"
android:fillAfter="true"
android:repeatMode="reverse" />
</set>
3.在activity_main中创建一个ImageView,并添加id
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<ImageView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="150dp"
android:background="#00F5FF"
android:layout_centerInParent="true"/>
</RelativeLayout>
4.最后,在MainActivity中调用
public class MainActivity extends AppCompatActivity {
ImageView iv;
Animation anim;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 找到动画视图
iv = findViewById(R.id.image);
// 加载需要执行的动画
anim = AnimationUtils.loadAnimation(this, R.anim.translate);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
//开始动画
iv.startAnimation(anim);
}
return true;
}
}
2.使用Java代码创建
MainActivity 中
public class MainActivity extends AppCompatActivity {
ImageView iv;
AnimationSet animationSet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 找到动画视图
iv = findViewById(R.id.image);
//创建动画集合 参数:是否共享插值器
animationSet = new AnimationSet(true);
//创建旋转动画
RotateAnimation rotate = new RotateAnimation(0, 360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
//创建平移动画
TranslateAnimation translate = new TranslateAnimation(0,500,0,500);
translate.setInterpolator(new AccelerateDecelerateInterpolator());
//创建透明的动画
AlphaAnimation alpha = new AlphaAnimation(1.0f, 0);
//创建缩放动画
ScaleAnimation scale = new ScaleAnimation(1.0f, 0, 1.0f, 0,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
//将动画全部加入动画集合 并设置属性
animationSet.addAnimation(rotate);
animationSet.addAnimation(translate);
animationSet.addAnimation(alpha);
animationSet.addAnimation(scale);
animationSet.setDuration(1000);
animationSet.setFillAfter(true);
animationSet.setRepeatMode(Animation.REVERSE);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
//开始动画
iv.startAnimation(animationSet);
}
return true;
}
}
实现效果图:
三、属性动画
所谓属性动画,就是直接对对象的属性进行操作,是真实的改变了对象的属性
属性动画可以看作是增强版的补间动画,与补间动画的不同之处体现在:
- 补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换,但是属性动画可以定义任何属性的变化。
- 补间动画只能对 UI 组件执行动画,但属性动画可以对任何对象执行动画。
与补间动画类似的是,属性动画也需要定义几个方面的属性:
- 动画持续时间。默认为 300ms,可以通过 android:duration 属性指定。
- 动画插值方式。通过 android:interploator 指定。
- 动画重复次数。通过 android:repeatCount 指定。
- 重复行为。通过 android:repeatMode 指定。
- 动画集。在属性资源文件中通过 <set .../> 来组合。
- 帧刷新率。指定多长时间播放一帧。默认为 10 ms。
继承关系如下:
接下来主要介绍ObjectAnimator的使用,因为其他类能实现的ObjectAnimator都能实现
1.在activity_main.xml中创建一个View视图
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".MainActivity">
<View
android:id="@+id/view"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:background="@color/colorAccent"></View>
</RelativeLayout>
2.在MainActivity中创建动画
public class MainActivity extends AppCompatActivity {
View v;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
v = findViewById(R.id.view);
}
// 透明度alpha
private void test1(){
/**
* 1.target 需要动画的控件
* 2.propertyName 控件的哪个属性
* 3. ...values 变化的值
* */
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(v, "alpha", 1,0,1);
alphaAnim.setDuration(2000);
alphaAnim.start();
}
// 旋转
private void test2(){
ObjectAnimator rotateAnim = ObjectAnimator.ofFloat(v, "rotation", 0,360);
rotateAnim.setDuration(1000);
rotateAnim.start();
}
// 缩放
private void test3(){
ObjectAnimator scaleAnim = ObjectAnimator.ofFloat(v,"scaleX", 1,0.5f);
scaleAnim.setDuration(1000);
scaleAnim.setRepeatMode(ValueAnimator.REVERSE);
ObjectAnimator scaleAnim2 = ObjectAnimator.ofFloat(v,"scaleY", 1,0.5f);
scaleAnim2.setDuration(1000);
scaleAnim2.setRepeatMode(ValueAnimator.REVERSE);
// with 同时执行
// after 后面执行
// before 前面执行
AnimatorSet animatorSet = new AnimatorSet();
// animatorSet.playSequentially(scaleAnim,scaleAnim2);
animatorSet.play(scaleAnim).after(scaleAnim2);
animatorSet.start();
}
private void test4(){
ObjectAnimator trans = ObjectAnimator.ofFloat(v, "translationX", v.getTranslationX()+100);
trans.setDuration(3000);
trans.start();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN){
test1();
test2();
test3();
test4();
}
return true;
}
}
实现效果: